mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 09:21:04 +00:00
Strip out old XCMP primitives (#823)
* WIP * WIp * Mostly get tests to compile * Fix adder collator * Remove more stuff * Revert some changes to av store * Fix av store tests * Nitpicks * Restore some things * Small changes * Remvoe unused error variants
This commit is contained in:
@@ -18,19 +18,18 @@
|
||||
|
||||
use rstd::prelude::*;
|
||||
use rstd::result;
|
||||
use rstd::collections::btree_map::BTreeMap;
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
use sp_runtime::traits::{
|
||||
Hash as HashT, BlakeTwo256, Saturating, One, Zero, Dispatchable,
|
||||
Hash as HashT, BlakeTwo256, Saturating, One, Dispatchable,
|
||||
AccountIdConversion, BadOrigin,
|
||||
};
|
||||
use frame_support::weights::SimpleDispatchInfo;
|
||||
use primitives::{
|
||||
Hash, Balance,
|
||||
Balance,
|
||||
parachain::{
|
||||
self, Id as ParaId, Chain, DutyRoster, AttestedCandidate, Statement, ParachainDispatchOrigin,
|
||||
UpwardMessage, BlockIngressRoots, ValidatorId, ActiveParas, CollatorId, Retriable,
|
||||
UpwardMessage, ValidatorId, ActiveParas, CollatorId, Retriable,
|
||||
NEW_HEADS_IDENTIFIER,
|
||||
},
|
||||
};
|
||||
@@ -66,11 +65,6 @@ impl<N: Saturating + One + PartialOrd + PartialEq + Clone> Iterator for BlockNum
|
||||
}
|
||||
}
|
||||
|
||||
// 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 }
|
||||
}
|
||||
|
||||
// wrapper trait because an associated type of `Currency<Self::AccountId,Balance=Balance>`
|
||||
// doesn't work.`
|
||||
pub trait ParachainCurrency<AccountId> {
|
||||
@@ -147,12 +141,6 @@ pub enum Origin {
|
||||
Parachain(ParaId),
|
||||
}
|
||||
|
||||
// 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
|
||||
];
|
||||
|
||||
/// Total number of individual messages allowed in the parachain -> relay-chain message queue.
|
||||
const MAX_QUEUE_COUNT: usize = 100;
|
||||
/// Total size of messages allowed in the parachain -> relay-chain message queue before which no
|
||||
@@ -169,18 +157,6 @@ decl_storage! {
|
||||
pub Code get(parachain_code): map hasher(blake2_256) ParaId => Option<Vec<u8>>;
|
||||
/// The heads of the parachains registered at present.
|
||||
pub Heads get(parachain_head): map hasher(blake2_256) ParaId => Option<Vec<u8>>;
|
||||
/// The watermark heights of the parachains registered at present.
|
||||
/// For every parachain, this is the block height from which all messages targeting
|
||||
/// that parachain have been processed. Can be `None` only if the parachain doesn't exist.
|
||||
pub Watermarks get(watermark): map hasher(blake2_256) ParaId => Option<T::BlockNumber>;
|
||||
|
||||
/// Unrouted ingress. Maps (BlockNumber, to_chain) pairs to [(from_chain, egress_root)].
|
||||
///
|
||||
/// There may be an entry under (i, p) in this map for every i between the parachain's
|
||||
/// watermark and the current block.
|
||||
pub UnroutedIngress:
|
||||
map hasher(blake2_256) (T::BlockNumber, ParaId) => Option<Vec<(ParaId, Hash)>>;
|
||||
|
||||
/// Messages ready to be dispatched onto the relay chain. It is subject to
|
||||
/// `MAX_MESSAGE_COUNT` and `WATERMARK_MESSAGE_SIZE`.
|
||||
pub RelayDispatchQueue: map hasher(blake2_256) ParaId => Vec<UpwardMessage>;
|
||||
@@ -219,14 +195,6 @@ decl_error! {
|
||||
QueueFull,
|
||||
/// The message origin is invalid.
|
||||
InvalidMessageOrigin,
|
||||
/// Egress routes should be in ascending order by parachain ID without duplicates.
|
||||
EgressOutOfOrder,
|
||||
/// A parachain cannot route a message to itself.
|
||||
SelfAddressed,
|
||||
/// The trie root cannot be empty.
|
||||
EmptyTrieRoot,
|
||||
/// Cannot route to a non-existing parachain.
|
||||
DestinationDoesNotExist,
|
||||
/// No validator group for parachain.
|
||||
NoValidatorGroup,
|
||||
/// Not enough validity votes for candidate.
|
||||
@@ -292,7 +260,6 @@ decl_module! {
|
||||
MAX_QUEUE_COUNT,
|
||||
WATERMARK_QUEUE_SIZE,
|
||||
)?;
|
||||
Self::check_egress_queue_roots(&head, &active_parachains)?;
|
||||
|
||||
let id = head.parachain_index();
|
||||
proceeded.push(id);
|
||||
@@ -301,15 +268,13 @@ decl_module! {
|
||||
}
|
||||
|
||||
let para_blocks = Self::check_candidates(&heads, &active_parachains)?;
|
||||
let current_number = <system::Module<T>>::block_number();
|
||||
|
||||
<attestations::Module<T>>::note_included(&heads, para_blocks);
|
||||
|
||||
Self::update_routing(
|
||||
current_number,
|
||||
&heads,
|
||||
);
|
||||
|
||||
|
||||
Self::dispatch_upward_messages(
|
||||
MAX_QUEUE_COUNT,
|
||||
WATERMARK_QUEUE_SIZE,
|
||||
@@ -351,12 +316,6 @@ impl<T: Trait> Module<T> {
|
||||
) {
|
||||
<Code>::insert(id, code);
|
||||
<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()));
|
||||
}
|
||||
|
||||
pub fn cleanup_para(
|
||||
@@ -364,19 +323,6 @@ impl<T: Trait> Module<T> {
|
||||
) {
|
||||
<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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Dispatch some messages from a parachain.
|
||||
@@ -415,8 +361,8 @@ impl<T: Trait> Module<T> {
|
||||
upward_messages.len() + count as usize == 1
|
||||
// ...or...
|
||||
|| (
|
||||
// ...the total messages in the queue ends up being no greater than the
|
||||
// limit...
|
||||
// ...the total messages in the queue ends up being no greater than the
|
||||
// limit...
|
||||
upward_messages.len() + count as usize <= max_queue_count
|
||||
&&
|
||||
// ...and the total size of the payloads in the queue ends up being no
|
||||
@@ -439,38 +385,14 @@ impl<T: Trait> Module<T> {
|
||||
/// Update routing information from the parachain heads. This queues upwards
|
||||
/// messages to the relay chain as well.
|
||||
fn update_routing(
|
||||
now: T::BlockNumber,
|
||||
heads: &[AttestedCandidate],
|
||||
) {
|
||||
// TODO: per-chain watermark
|
||||
// https://github.com/paritytech/polkadot/issues/286
|
||||
let watermark = now.saturating_sub(One::one());
|
||||
|
||||
let mut ingress_update = BTreeMap::new();
|
||||
|
||||
// we sort them in order to provide a fast lookup to ensure we can avoid duplicates in the
|
||||
// needs_dispatch queue.
|
||||
let mut ordered_needs_dispatch = NeedsDispatch::get();
|
||||
|
||||
for head in heads.iter() {
|
||||
let id = head.parachain_index();
|
||||
<Heads>::insert(id, &head.candidate.head_data.0);
|
||||
|
||||
let last_watermark = <Watermarks<T>>::mutate(id, |mark| {
|
||||
rstd::mem::replace(mark, Some(watermark))
|
||||
});
|
||||
|
||||
if let Some(last_watermark) = last_watermark {
|
||||
// Discard routed ingress.
|
||||
for routed_height in number_range(last_watermark, watermark) {
|
||||
<UnroutedIngress<T>>::remove(&(routed_height, id));
|
||||
}
|
||||
}
|
||||
|
||||
// place our egress root to `to` into the ingress table for (now, `to`).
|
||||
for &(to, root) in &head.candidate.egress_queue_roots {
|
||||
ingress_update.entry(to).or_insert_with(Vec::new).push((id, root));
|
||||
}
|
||||
|
||||
// Queue up upwards messages (from parachains to relay chain).
|
||||
Self::queue_upward_messages(
|
||||
@@ -481,11 +403,6 @@ impl<T: Trait> Module<T> {
|
||||
}
|
||||
|
||||
NeedsDispatch::put(ordered_needs_dispatch);
|
||||
|
||||
// apply the ingress update.
|
||||
for (to, ingress_roots) in ingress_update {
|
||||
<UnroutedIngress<T>>::insert((now, to), ingress_roots);
|
||||
}
|
||||
}
|
||||
|
||||
/// Place any new upward messages into our queue for later dispatch.
|
||||
@@ -623,32 +540,6 @@ impl<T: Trait> Module<T> {
|
||||
(DutyRoster { validator_duty: roles_val, }, orig_seed)
|
||||
}
|
||||
|
||||
/// Calculate the ingress to a specific parachain.
|
||||
/// If `since` is provided, only messages since (including those in) that block
|
||||
/// will be included.
|
||||
/// Complexity: O(n) in the number of blocks since the supplied block.
|
||||
/// invoked off-chain.
|
||||
///
|
||||
/// Yields a structure containing all unrouted ingress to the parachain.
|
||||
pub fn ingress(to: ParaId, since: Option<T::BlockNumber>) -> Option<Vec<(T::BlockNumber, BlockIngressRoots)>> {
|
||||
let watermark = <Watermarks<T>>::get(to)?;
|
||||
let now = <system::Module<T>>::block_number();
|
||||
|
||||
let watermark_since = watermark.saturating_add(One::one());
|
||||
let since = rstd::cmp::max(since.unwrap_or(Zero::zero()), watermark_since);
|
||||
if since > now {
|
||||
return Some(Vec::new());
|
||||
}
|
||||
|
||||
Some(number_range(since, now)
|
||||
.filter_map(|unrouted_height| {
|
||||
<UnroutedIngress<T>>::get(&(unrouted_height, to)).map(|roots| {
|
||||
(unrouted_height, BlockIngressRoots(roots))
|
||||
})
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// Get the parachain status necessary for validation.
|
||||
pub fn parachain_status(id: ¶chain::Id) -> Option<parachain::Status> {
|
||||
let balance = T::ParachainCurrency::free_balance(*id);
|
||||
@@ -669,42 +560,6 @@ impl<T: Trait> Module<T> {
|
||||
T::ActiveParachains::active_paras()
|
||||
}
|
||||
|
||||
fn check_egress_queue_roots(
|
||||
head: &AttestedCandidate,
|
||||
active_parachains: &[(ParaId, Option<(CollatorId, Retriable)>)]
|
||||
) -> DispatchResult {
|
||||
let mut last_egress_id = None;
|
||||
let mut iter = active_parachains.iter().map(|x| x.0);
|
||||
for (egress_para_id, root) in &head.candidate.egress_queue_roots {
|
||||
// egress routes should be ascending order by parachain ID without duplicate.
|
||||
ensure!(
|
||||
last_egress_id.as_ref().map_or(true, |x| x < &egress_para_id),
|
||||
Error::<T>::EgressOutOfOrder,
|
||||
);
|
||||
|
||||
// a parachain can't route to self
|
||||
ensure!(
|
||||
*egress_para_id != head.candidate.parachain_index,
|
||||
Error::<T>::SelfAddressed,
|
||||
);
|
||||
|
||||
// no empty trie roots
|
||||
ensure!(
|
||||
*root != EMPTY_TRIE_ROOT.into(),
|
||||
Error::<T>::EmptyTrieRoot,
|
||||
);
|
||||
|
||||
// can't route to a parachain which doesn't exist
|
||||
ensure!(
|
||||
iter.find(|x| x == egress_para_id).is_some(),
|
||||
Error::<T>::DestinationDoesNotExist,
|
||||
);
|
||||
|
||||
last_egress_id = Some(egress_para_id)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// check the attestations on these candidates. The candidates should have been checked
|
||||
// that each candidates' chain ID is valid.
|
||||
fn check_candidates(
|
||||
@@ -984,12 +839,18 @@ mod tests {
|
||||
};
|
||||
use keyring::Sr25519Keyring;
|
||||
use frame_support::{
|
||||
impl_outer_origin, impl_outer_dispatch, assert_ok, assert_err, assert_noop, parameter_types,
|
||||
impl_outer_origin, impl_outer_dispatch, assert_ok, assert_err, parameter_types,
|
||||
};
|
||||
use crate::parachains;
|
||||
use crate::registrar;
|
||||
use crate::slots;
|
||||
|
||||
// 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
|
||||
];
|
||||
|
||||
impl_outer_origin! {
|
||||
pub enum Origin for Test {
|
||||
parachains
|
||||
@@ -1312,25 +1173,6 @@ mod tests {
|
||||
candidate.validator_indices = validator_indices;
|
||||
}
|
||||
|
||||
fn new_candidate_with_egress_roots(egress_queue_roots: Vec<(ParaId, H256)>) -> AttestedCandidate {
|
||||
AttestedCandidate {
|
||||
validity_votes: vec![],
|
||||
validator_indices: BitVec::new(),
|
||||
candidate: CandidateReceipt {
|
||||
parachain_index: 0.into(),
|
||||
collator: Default::default(),
|
||||
signature: Default::default(),
|
||||
head_data: HeadData(vec![1, 2, 3]),
|
||||
parent_head: HeadData(vec![]),
|
||||
egress_queue_roots,
|
||||
fees: 0,
|
||||
block_data_hash: Default::default(),
|
||||
upward_messages: vec![],
|
||||
erasure_root: [1u8; 32].into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new_candidate_with_upward_messages(
|
||||
id: u32,
|
||||
upward_messages: Vec<(ParachainDispatchOrigin, Vec<u8>)>
|
||||
@@ -1344,7 +1186,6 @@ mod tests {
|
||||
signature: Default::default(),
|
||||
head_data: HeadData(vec![1, 2, 3]),
|
||||
parent_head: HeadData(vec![]),
|
||||
egress_queue_roots: vec![],
|
||||
fees: 0,
|
||||
block_data_hash: Default::default(),
|
||||
upward_messages: upward_messages.into_iter()
|
||||
@@ -1755,7 +1596,6 @@ mod tests {
|
||||
signature: Default::default(),
|
||||
head_data: HeadData(vec![1, 2, 3]),
|
||||
parent_head: HeadData(vec![]),
|
||||
egress_queue_roots: vec![],
|
||||
fees: 0,
|
||||
block_data_hash: Default::default(),
|
||||
upward_messages: vec![],
|
||||
@@ -1788,7 +1628,6 @@ mod tests {
|
||||
signature: Default::default(),
|
||||
head_data: HeadData(vec![1, 2, 3]),
|
||||
parent_head: HeadData(vec![]),
|
||||
egress_queue_roots: vec![],
|
||||
fees: 0,
|
||||
block_data_hash: Default::default(),
|
||||
upward_messages: vec![],
|
||||
@@ -1805,7 +1644,6 @@ mod tests {
|
||||
signature: Default::default(),
|
||||
head_data: HeadData(vec![2, 3, 4]),
|
||||
parent_head: HeadData(vec![]),
|
||||
egress_queue_roots: vec![],
|
||||
fees: 0,
|
||||
block_data_hash: Default::default(),
|
||||
upward_messages: vec![],
|
||||
@@ -1846,7 +1684,6 @@ mod tests {
|
||||
signature: Default::default(),
|
||||
head_data: HeadData(vec![1, 2, 3]),
|
||||
parent_head: HeadData(vec![]),
|
||||
egress_queue_roots: vec![],
|
||||
fees: 0,
|
||||
block_data_hash: Default::default(),
|
||||
upward_messages: vec![],
|
||||
@@ -1885,7 +1722,6 @@ mod tests {
|
||||
signature: Default::default(),
|
||||
head_data: HeadData(vec![1, 2, 3]),
|
||||
parent_head: HeadData(vec![]),
|
||||
egress_queue_roots: vec![],
|
||||
fees: 0,
|
||||
block_data_hash: Default::default(),
|
||||
upward_messages: vec![],
|
||||
@@ -1906,234 +1742,6 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ingress_works() {
|
||||
let parachains = vec![
|
||||
(0u32.into(), vec![], vec![]),
|
||||
(1u32.into(), vec![], vec![]),
|
||||
(99u32.into(), vec![1, 2, 3], vec![4, 5, 6]),
|
||||
];
|
||||
|
||||
new_test_ext(parachains).execute_with(|| {
|
||||
assert_eq!(Parachains::ingress(ParaId::from(1), None), Some(Vec::new()));
|
||||
assert_eq!(Parachains::ingress(ParaId::from(99), None), Some(Vec::new()));
|
||||
|
||||
init_block();
|
||||
|
||||
for i in 1..10 {
|
||||
run_to_block(i);
|
||||
|
||||
let from_a = vec![(1.into(), [i as u8; 32].into())];
|
||||
|
||||
let parent_head = HeadData(if i == 1 {
|
||||
vec![]
|
||||
} else {
|
||||
vec![1, 2, 3]
|
||||
});
|
||||
|
||||
let mut candidate_a = AttestedCandidate {
|
||||
validity_votes: vec![],
|
||||
validator_indices: BitVec::new(),
|
||||
candidate: CandidateReceipt {
|
||||
parachain_index: 0.into(),
|
||||
collator: Default::default(),
|
||||
signature: Default::default(),
|
||||
head_data: HeadData(vec![1, 2, 3]),
|
||||
parent_head: parent_head.clone(),
|
||||
egress_queue_roots: from_a.clone(),
|
||||
fees: 0,
|
||||
block_data_hash: Default::default(),
|
||||
upward_messages: vec![],
|
||||
erasure_root: [1u8; 32].into(),
|
||||
}
|
||||
};
|
||||
|
||||
let from_b = vec![(99.into(), [i as u8; 32].into())];
|
||||
let mut candidate_b = AttestedCandidate {
|
||||
validity_votes: vec![],
|
||||
validator_indices: BitVec::new(),
|
||||
candidate: CandidateReceipt {
|
||||
parachain_index: 1.into(),
|
||||
collator: Default::default(),
|
||||
signature: Default::default(),
|
||||
head_data: HeadData(vec![1, 2, 3]),
|
||||
parent_head,
|
||||
egress_queue_roots: from_b.clone(),
|
||||
fees: 0,
|
||||
block_data_hash: Default::default(),
|
||||
upward_messages: vec![],
|
||||
erasure_root: [1u8; 32].into(),
|
||||
}
|
||||
};
|
||||
|
||||
make_attestations(&mut candidate_a);
|
||||
make_attestations(&mut candidate_b);
|
||||
|
||||
assert_ok!(Parachains::dispatch(
|
||||
set_heads(vec![candidate_a, candidate_b]),
|
||||
Origin::NONE,
|
||||
));
|
||||
}
|
||||
|
||||
run_to_block(10);
|
||||
assert_ok!(Parachains::dispatch(
|
||||
set_heads(vec![]),
|
||||
Origin::NONE,
|
||||
));
|
||||
|
||||
// parachain 1 has had a bunch of parachain candidates included,
|
||||
// which raises the watermark.
|
||||
assert_eq!(
|
||||
Parachains::ingress(ParaId::from(1), None),
|
||||
Some(vec![
|
||||
(9, BlockIngressRoots(vec![
|
||||
(0.into(), [9; 32].into())
|
||||
]))
|
||||
]),
|
||||
);
|
||||
|
||||
// parachain 99 hasn't had any candidates included, so the
|
||||
// ingress is piling up.
|
||||
assert_eq!(
|
||||
Parachains::ingress(ParaId::from(99), None),
|
||||
Some((1..10).map(|i| (i, BlockIngressRoots(
|
||||
vec![(1.into(), [i as u8; 32].into())]
|
||||
))).collect::<Vec<_>>()),
|
||||
);
|
||||
|
||||
assert_ok!(Registrar::deregister_para(Origin::ROOT, 1u32.into()));
|
||||
|
||||
// after deregistering, there is no ingress to 1, but unrouted messages
|
||||
// from 1 stick around.
|
||||
assert_eq!(Parachains::ingress(ParaId::from(1), None), None);
|
||||
assert_eq!(Parachains::ingress(ParaId::from(99), None), Some((1..10).map(|i| (i, BlockIngressRoots(
|
||||
vec![(1.into(), [i as u8; 32].into())]
|
||||
))).collect::<Vec<_>>()));
|
||||
|
||||
run_to_block(11);
|
||||
|
||||
let mut candidate_c = AttestedCandidate {
|
||||
validity_votes: vec![],
|
||||
validator_indices: BitVec::new(),
|
||||
candidate: CandidateReceipt {
|
||||
parachain_index: 99.into(),
|
||||
collator: Default::default(),
|
||||
signature: Default::default(),
|
||||
head_data: HeadData(vec![1, 2, 3]),
|
||||
parent_head: HeadData(vec![4, 5, 6]),
|
||||
egress_queue_roots: Vec::new(),
|
||||
fees: 0,
|
||||
block_data_hash: Default::default(),
|
||||
upward_messages: vec![],
|
||||
erasure_root: [1u8; 32].into(),
|
||||
}
|
||||
};
|
||||
make_attestations(&mut candidate_c);
|
||||
|
||||
assert_ok!(Parachains::dispatch(
|
||||
set_heads(vec![candidate_c]),
|
||||
Origin::NONE,
|
||||
));
|
||||
|
||||
run_to_block(12);
|
||||
|
||||
// at the next block, ingress to 99 should be empty.
|
||||
assert_eq!(Parachains::ingress(ParaId::from(99), None), Some(Vec::new()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn egress_routed_to_non_existent_parachain_is_rejected() {
|
||||
// That no parachain is routed to which doesn't exist
|
||||
let parachains = vec![
|
||||
(0u32.into(), vec![], vec![]),
|
||||
(1u32.into(), vec![], vec![]),
|
||||
];
|
||||
|
||||
new_test_ext(parachains.clone()).execute_with(|| {
|
||||
run_to_block(2);
|
||||
// parachain 99 does not exist
|
||||
let non_existent = vec![(99.into(), [1; 32].into())];
|
||||
let mut candidate = new_candidate_with_egress_roots(non_existent);
|
||||
|
||||
make_attestations(&mut candidate);
|
||||
|
||||
assert_noop!(
|
||||
Parachains::set_heads(Origin::NONE, vec![candidate.clone()]),
|
||||
Error::<Test>::DestinationDoesNotExist
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn egress_routed_to_self_is_rejected() {
|
||||
// That the parachain doesn't route to self
|
||||
let parachains = vec![
|
||||
(0u32.into(), vec![], vec![]),
|
||||
(1u32.into(), vec![], vec![]),
|
||||
];
|
||||
|
||||
new_test_ext(parachains.clone()).execute_with(|| {
|
||||
run_to_block(2);
|
||||
// parachain 0 is self
|
||||
let to_self = vec![(0.into(), [1; 32].into())];
|
||||
let mut candidate = new_candidate_with_egress_roots(to_self);
|
||||
|
||||
make_attestations(&mut candidate);
|
||||
|
||||
assert_noop!(
|
||||
Parachains::set_heads(Origin::NONE, vec![candidate.clone()]),
|
||||
Error::<Test>::SelfAddressed
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn egress_queue_roots_out_of_order_rejected() {
|
||||
// That the list of egress queue roots is in ascending order by `ParaId`.
|
||||
let parachains = vec![
|
||||
(0u32.into(), vec![], vec![]),
|
||||
(1u32.into(), vec![], vec![]),
|
||||
];
|
||||
|
||||
new_test_ext(parachains.clone()).execute_with(|| {
|
||||
run_to_block(2);
|
||||
// parachain 0 is self
|
||||
let out_of_order = vec![(1.into(), [1; 32].into()), ((0.into(), [1; 32].into()))];
|
||||
let mut candidate = new_candidate_with_egress_roots(out_of_order);
|
||||
|
||||
make_attestations(&mut candidate);
|
||||
|
||||
assert_noop!(
|
||||
Parachains::set_heads(Origin::NONE, vec![candidate.clone()]),
|
||||
Error::<Test>::EgressOutOfOrder
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn egress_queue_roots_empty_trie_roots_rejected() {
|
||||
let parachains = vec![
|
||||
(0u32.into(), vec![], vec![]),
|
||||
(1u32.into(), vec![], vec![]),
|
||||
(2u32.into(), vec![], vec![]),
|
||||
];
|
||||
|
||||
new_test_ext(parachains.clone()).execute_with(|| {
|
||||
run_to_block(2);
|
||||
// parachain 0 is self
|
||||
let contains_empty_trie_root = vec![(1.into(), [1; 32].into()), ((2.into(), EMPTY_TRIE_ROOT.into()))];
|
||||
let mut candidate = new_candidate_with_egress_roots(contains_empty_trie_root);
|
||||
|
||||
make_attestations(&mut candidate);
|
||||
|
||||
assert_noop!(
|
||||
Parachains::set_heads(Origin::NONE, vec![candidate.clone()]),
|
||||
Error::<Test>::EmptyTrieRoot
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_trie_root_const_is_blake2_hashed_null_node() {
|
||||
let hashed_null_node = <NodeCodec<Blake2Hasher> as trie_db::NodeCodec>::hashed_null_node();
|
||||
|
||||
Reference in New Issue
Block a user