Make work with Substrate master (#36)

* Fix up wasm runtime build

* Fixes for runtime

* Fix.

* More fixes

* Runtime builds on native.

* Native and wasm both build without warnings.

* Fix runtime tests.

* Merge #20

* Final fix for native runtime.

* Compile polkadot wo consensus

* Reverted changes to polkadot-consensus

* reintroduce minimal subset of consensus

* reintroduce checked_block to runtime for std

* polkadot_consensus compiles without most of the code

* remove checked_block again and do more checks in parachains for runtime

* uncomment proposer

* remove offline tracker

* extract out parachain-attestation logic from proposal directly

* reintroduce transaction_pool

* write some custom aura verification logic for the block verifier

* use transaction pool in more generic way

* service compiles again

* polkadot-network and tests pass

* remove unused session_key function from router

* everything but CLI compiles due to service hell

* Fixes compilation of `polkadot_cli`

* everything compiles

* update adder wasm
This commit is contained in:
Gav Wood
2018-11-25 11:25:36 +01:00
committed by GitHub
parent e68cd9df10
commit c31f8168df
52 changed files with 3281 additions and 4669 deletions
+173 -153
View File
@@ -19,7 +19,8 @@
use rstd::prelude::*;
use codec::Decode;
use runtime_primitives::traits::{Hash, BlakeTwo256, OnFinalise};
use sr_primitives::{RuntimeString, traits::{Extrinsic, Block as BlockT,
Hash, BlakeTwo256, ProvideInherent}};
use primitives::parachain::{Id, Chain, DutyRoster, CandidateReceipt};
use {system, session};
@@ -27,43 +28,133 @@ use srml_support::{StorageValue, StorageMap};
use srml_support::dispatch::Result;
#[cfg(any(feature = "std", test))]
use rstd::marker::PhantomData;
use sr_primitives::{self, ChildrenStorageMap};
#[cfg(any(feature = "std", test))]
use runtime_primitives;
use system::ensure_inherent;
#[cfg(any(feature = "std", test))]
use std::collections::HashMap;
use system::{ensure_root, ensure_inherent};
pub trait Trait: system::Trait<Hash = ::primitives::Hash> + session::Trait {
pub trait Trait: session::Trait {
/// The position of the set_heads call in the block.
const SET_POSITION: u32;
}
decl_storage! {
trait Store for Module<T: Trait> as Parachains {
// Vector of all parachain IDs.
pub Parachains get(active_parachains): Vec<Id>;
// The parachains registered at present.
pub Code get(parachain_code): map Id => Option<Vec<u8>>;
// The heads of the parachains registered at present. these are kept sorted.
pub Heads get(parachain_head): map Id => Option<Vec<u8>>;
// Did the parachain heads get updated in this block?
DidUpdate: bool;
}
add_extra_genesis {
config(parachains): Vec<(Id, Vec<u8>, Vec<u8>)>;
build(|storage: &mut sr_primitives::StorageMap, _: &mut ChildrenStorageMap, config: &GenesisConfig<T>| {
use codec::Encode;
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();
storage.insert(GenesisConfig::<T>::hash(<Parachains<T>>::key()).to_vec(), only_ids.encode());
for (id, code, genesis) in p {
let code_key = GenesisConfig::<T>::hash(&<Code<T>>::key_for(&id)).to_vec();
let head_key = GenesisConfig::<T>::hash(&<Heads<T>>::key_for(&id)).to_vec();
storage.insert(code_key, code.encode());
storage.insert(head_key, genesis.encode());
}
});
}
}
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<CandidateReceipt>) -> Result;
fn set_heads(origin, heads: Vec<CandidateReceipt>) -> Result {
ensure_inherent(origin)?;
ensure!(!<DidUpdate<T>>::exists(), "Parachain heads must be updated only once in the block");
ensure!(
<system::Module<T>>::extrinsic_index() == Some(T::SET_POSITION),
"Parachain heads update extrinsic must be at position {} in the block"
// , T::SET_POSITION
);
fn register_parachain(origin, id: Id, code: Vec<u8>, initial_head_data: Vec<u8>) -> Result;
fn deregister_parachain(origin, id: Id) -> Result;
}
}
let active_parachains = Self::active_parachains();
decl_storage! {
trait Store for Module<T: Trait> as Parachains {
// Vector of all parachain IDs.
pub Parachains get(active_parachains): default Vec<Id>;
// The parachains registered at present.
pub Code get(parachain_code): map [ Id => Vec<u8> ];
// The heads of the parachains registered at present. these are kept sorted.
pub Heads get(parachain_head): map [ Id => Vec<u8> ];
// perform integrity checks before writing to storage.
{
let n_parachains = active_parachains.len();
ensure!(heads.len() <= n_parachains, "Too many parachain candidates");
// Did the parachain heads get updated in this block?
DidUpdate: default bool;
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 {}"
);
last_id = Some(head.parachain_index);
}
}
for head in heads {
let id = head.parachain_index.clone();
<Heads<T>>::insert(id, head.head_data.0);
}
<DidUpdate<T>>::put(true);
Ok(())
}
/// Register a parachain with given code.
/// Fails if given ID is already used.
pub fn register_parachain(id: Id, 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(())
}
/// Deregister a parachain with given id
pub fn deregister_parachain(id: Id) -> Result {
let mut parachains = Self::active_parachains();
match parachains.binary_search(&id) {
Ok(idx) => { parachains.remove(idx); }
Err(_) => {}
}
<Code<T>>::remove(id);
<Heads<T>>::remove(id);
<Parachains<T>>::put(parachains);
Ok(())
}
fn on_finalise(_n: T::BlockNumber) {
assert!(<Self as Store>::DidUpdate::take(), "Parachain heads must be updated once in the block");
}
}
}
@@ -85,7 +176,7 @@ impl<T: Trait> Module<T> {
let mut roles_gua = roles_val.clone();
let mut random_seed = system::Module::<T>::random_seed().to_vec();
let mut random_seed = system::Module::<T>::random_seed().as_ref().to_vec();
random_seed.extend(b"validator_role_pairs");
let mut seed = BlakeTwo256::hash(&random_seed);
@@ -103,7 +194,7 @@ impl<T: Trait> Module<T> {
if offset == 24 {
// into the last 8 bytes - rehash to gather new entropy
seed = BlakeTwo256::hash(&seed);
seed = BlakeTwo256::hash(seed.as_ref());
}
// exchange last item with randomly chosen first.
@@ -117,134 +208,60 @@ impl<T: Trait> Module<T> {
}
}
/// Register a parachain with given code.
/// Fails if given ID is already used.
pub fn register_parachain(origin: T::Origin, id: Id, code: Vec<u8>, initial_head_data: Vec<u8>) -> Result {
ensure_root(origin)?;
let mut parachains = Self::active_parachains();
match parachains.binary_search(&id) {
Ok(_) => fail!("Parachain already exists"),
Err(idx) => parachains.insert(idx, id),
}
/*
// TODO: Consider integrating if needed.
/// Extract the parachain heads from the block.
pub fn parachain_heads(&self) -> &[CandidateReceipt] {
let x = self.inner.extrinsics.get(PARACHAINS_SET_POSITION as usize).and_then(|xt| match xt.function {
Call::Parachains(ParachainsCall::set_heads(ref x)) => Some(&x[..]),
_ => None
});
<Code<T>>::insert(id, code);
<Parachains<T>>::put(parachains);
<Heads<T>>::insert(id, initial_head_data);
match x {
Some(x) => x,
None => panic!("Invalid polkadot block asserted at {:?}", self.file_line),
}
}
*/
}
impl<T: Trait> ProvideInherent for Module<T> {
type Inherent = Vec<CandidateReceipt>;
type Call = Call<T>;
type Error = RuntimeString;
fn create_inherent_extrinsics(data: Self::Inherent) -> Vec<(u32, Self::Call)> {
vec![(T::SET_POSITION, Call::set_heads(data))]
}
fn check_inherent<Block: BlockT, F: Fn(&Block::Extrinsic) -> Option<&Self::Call>>(
block: &Block, _data: Self::Inherent, extract_function: &F
) -> ::rstd::result::Result<(), Self::Error> {
let has_heads = block
.extrinsics()
.get(T::SET_POSITION as usize)
.map_or(false, |xt| {
xt.is_signed() == Some(true) && match extract_function(&xt) {
Some(Call::set_heads(_)) => true,
_ => false,
}
});
if !has_heads { return Err("No valid parachains inherent in block".into()) }
Ok(())
}
/// Deregister a parachain with given id
pub fn deregister_parachain(origin: T::Origin, id: Id) -> Result {
ensure_root(origin)?;
let mut parachains = Self::active_parachains();
match parachains.binary_search(&id) {
Ok(idx) => { parachains.remove(idx); }
Err(_) => {}
}
<Code<T>>::remove(id);
<Heads<T>>::remove(id);
<Parachains<T>>::put(parachains);
Ok(())
}
fn set_heads(origin: T::Origin, heads: Vec<CandidateReceipt>) -> Result {
ensure_inherent(origin)?;
ensure!(!<DidUpdate<T>>::exists(), "Parachain heads must be updated only once in the block");
ensure!(
<system::Module<T>>::extrinsic_index() == Some(T::SET_POSITION),
"Parachain heads update extrinsic must be at position {} in the block"
// , T::SET_POSITION
);
let active_parachains = Self::active_parachains();
let mut iter = active_parachains.iter();
// perform this check before writing to storage.
for head in &heads {
ensure!(
iter.find(|&p| p == &head.parachain_index).is_some(),
"Submitted candidate for unregistered or out-of-order parachain {}"
// , head.parachain_index.into_inner()
);
}
for head in heads {
let id = head.parachain_index.clone();
<Heads<T>>::insert(id, head.head_data.0);
}
<DidUpdate<T>>::put(true);
Ok(())
}
}
impl<T: Trait> OnFinalise<T::BlockNumber> for Module<T> {
fn on_finalise(_n: T::BlockNumber) {
assert!(<Self as Store>::DidUpdate::take(), "Parachain heads must be updated once in the block");
}
}
/// Parachains module genesis configuration.
#[cfg(any(feature = "std", test))]
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(deny_unknown_fields)]
pub struct GenesisConfig<T: Trait> {
/// The initial parachains, mapped to code and initial head data
pub parachains: Vec<(Id, Vec<u8>, Vec<u8>)>,
/// Phantom data.
#[serde(skip)]
pub phantom: PhantomData<T>,
}
#[cfg(any(feature = "std", test))]
impl<T: Trait> Default for GenesisConfig<T> {
fn default() -> Self {
GenesisConfig {
parachains: Vec::new(),
phantom: PhantomData,
}
}
}
#[cfg(any(feature = "std", test))]
impl<T: Trait> runtime_primitives::BuildStorage for GenesisConfig<T>
{
fn build_storage(mut self) -> ::std::result::Result<HashMap<Vec<u8>, Vec<u8>>, String> {
use codec::Encode;
self.parachains.sort_unstable_by_key(|&(ref id, _, _)| id.clone());
self.parachains.dedup_by_key(|&mut (ref id, _, _)| id.clone());
let only_ids: Vec<_> = self.parachains.iter().map(|&(ref id, _, _)| id).cloned().collect();
let mut map: HashMap<_, _> = map![
Self::hash(<Parachains<T>>::key()).to_vec() => only_ids.encode()
];
for (id, code, genesis) in self.parachains {
let code_key = Self::hash(&<Code<T>>::key_for(&id)).to_vec();
let head_key = Self::hash(&<Heads<T>>::key_for(&id)).to_vec();
map.insert(code_key, code.encode());
map.insert(head_key, genesis.encode());
}
Ok(map)
}
}
#[cfg(test)]
mod tests {
use super::*;
use runtime_io::{TestExternalities, with_externalities};
use rstd::marker::PhantomData;
use sr_io::{TestExternalities, with_externalities};
use substrate_primitives::{H256, Blake2Hasher};
use runtime_primitives::BuildStorage;
use runtime_primitives::traits::{Identity, BlakeTwo256};
use runtime_primitives::testing::{Digest, Header};
use sr_primitives::BuildStorage;
use sr_primitives::traits::{Identity, BlakeTwo256};
use sr_primitives::testing::{Digest, Header, DigestItem};
use {consensus, timestamp};
impl_outer_origin! {
@@ -257,7 +274,7 @@ mod tests {
const NOTE_OFFLINE_POSITION: u32 = 1;
type SessionKey = u64;
type OnOfflineValidator = ();
type Log = u64;
type Log = DigestItem;
}
impl system::Trait for Test {
type Origin = Origin;
@@ -269,6 +286,7 @@ mod tests {
type AccountId = u64;
type Header = Header;
type Event = ();
type Log = DigestItem;
}
impl session::Trait for Test {
type ConvertAccountIdToSessionKey = Identity;
@@ -286,19 +304,21 @@ mod tests {
type Parachains = Module<Test>;
fn new_test_ext(parachains: Vec<(Id, Vec<u8>, Vec<u8>)>) -> TestExternalities<Blake2Hasher> {
let mut t = system::GenesisConfig::<Test>::default().build_storage().unwrap();
let mut t = system::GenesisConfig::<Test>::default().build_storage().unwrap().0;
t.extend(consensus::GenesisConfig::<Test>{
code: vec![],
authorities: vec![1, 2, 3],
}.build_storage().unwrap());
_genesis_phantom_data: PhantomData,
}.build_storage().unwrap().0);
t.extend(session::GenesisConfig::<Test>{
session_length: 1000,
validators: vec![1, 2, 3, 4, 5, 6, 7, 8],
}.build_storage().unwrap());
_genesis_phantom_data: PhantomData,
}.build_storage().unwrap().0);
t.extend(GenesisConfig::<Test>{
parachains: parachains,
phantom: PhantomData,
}.build_storage().unwrap());
_genesis_phantom_data: PhantomData,
}.build_storage().unwrap().0);
t.into()
}
@@ -329,12 +349,12 @@ mod tests {
assert_eq!(Parachains::parachain_code(&5u32.into()), Some(vec![1,2,3]));
assert_eq!(Parachains::parachain_code(&100u32.into()), Some(vec![4,5,6]));
assert_ok!(Parachains::register_parachain(Origin::ROOT, 99u32.into(), vec![7,8,9], vec![1, 1, 1]));
assert_ok!(Parachains::register_parachain(99u32.into(), vec![7,8,9], vec![1, 1, 1]));
assert_eq!(Parachains::active_parachains(), vec![5u32.into(), 99u32.into(), 100u32.into()]);
assert_eq!(Parachains::parachain_code(&99u32.into()), Some(vec![7,8,9]));
assert_ok!(Parachains::deregister_parachain(Origin::ROOT, 5u32.into()));
assert_ok!(Parachains::deregister_parachain(5u32.into()));
assert_eq!(Parachains::active_parachains(), vec![99u32.into(), 100u32.into()]);
assert_eq!(Parachains::parachain_code(&5u32.into()), None);