diff --git a/polkadot/availability-store/src/lib.rs b/polkadot/availability-store/src/lib.rs index 7c0c219d7e..f726b1c0cb 100644 --- a/polkadot/availability-store/src/lib.rs +++ b/polkadot/availability-store/src/lib.rs @@ -28,8 +28,7 @@ use keystore::KeyStorePtr; use polkadot_primitives::{ Hash, Block, parachain::{ - Id as ParaId, BlockData, CandidateReceipt, Message, AvailableMessages, ErasureChunk, - ParachainHost, + Id as ParaId, BlockData, CandidateReceipt, ErasureChunk, ParachainHost }, }; use sp_runtime::traits::{BlakeTwo256, Hash as HashT, HasherFor}; @@ -126,10 +125,6 @@ pub struct Data { pub parachain_id: ParaId, /// Block data. pub block_data: BlockData, - /// Outgoing message queues from execution of the block, if any. - /// - /// The tuple pairs the message queue root and the queue data. - pub outgoing_queues: Option, } /// Handle to the availability store. @@ -384,9 +379,4 @@ impl Store { { self.inner.block_data_by_candidate(relay_parent, candidate_hash) } - - /// Query message queue data by message queue root hash. - pub fn queue_by_root(&self, queue_root: &Hash) -> Option> { - self.inner.queue_by_root(queue_root) - } } diff --git a/polkadot/availability-store/src/store.rs b/polkadot/availability-store/src/store.rs index 6df777278f..d7aa60443a 100644 --- a/polkadot/availability-store/src/store.rs +++ b/polkadot/availability-store/src/store.rs @@ -21,9 +21,7 @@ use codec::{Encode, Decode}; use polkadot_erasure_coding::{self as erasure}; use polkadot_primitives::{ Hash, - parachain::{ - BlockData, CandidateReceipt, Message, ErasureChunk - }, + parachain::{BlockData, CandidateReceipt, ErasureChunk}, }; use log::{trace, warn}; @@ -130,18 +128,6 @@ impl Store { data.block_data.encode() ); - if let Some(outgoing_queues) = data.outgoing_queues { - // This is kept forever and not pruned. - for (root, messages) in outgoing_queues.0 { - tx.put_vec( - columns::DATA, - root.as_ref(), - messages.encode(), - ); - } - - } - self.inner.write(tx) } @@ -287,14 +273,13 @@ impl Store { columns::DATA, &block_data_key(&relay_parent, &receipt.block_data_hash) ) { - if let Ok((block_data, outgoing_queues)) = erasure::reconstruct( + if let Ok(block_data) = erasure::reconstruct( n_validators as usize, v.iter().map(|chunk| (chunk.chunk.as_ref(), chunk.index as usize))) { self.make_available(Data { relay_parent: *relay_parent, parachain_id: receipt.parachain_index, block_data, - outgoing_queues, })?; } } @@ -387,11 +372,6 @@ impl Store { }) } - /// Query message queue data by message queue root hash. - pub fn queue_by_root(&self, queue_root: &Hash) -> Option> { - self.query_inner(columns::DATA, queue_root.as_ref()) - } - fn block_hash_to_candidate_hash(&self, block_hash: Hash) -> Option { self.query_inner(columns::META, &block_to_candidate_key(&block_hash)) } @@ -414,8 +394,8 @@ impl Store { #[cfg(test)] mod tests { use super::*; - use polkadot_erasure_coding::{self as erasure}; - use polkadot_primitives::parachain::{Id as ParaId, AvailableMessages}; + use polkadot_erasure_coding as erasure; + use polkadot_primitives::parachain::Id as ParaId; #[test] fn finalization_removes_unneeded() { @@ -444,14 +424,12 @@ mod tests { relay_parent, parachain_id: para_id_1, block_data: block_data_1.clone(), - outgoing_queues: None, }).unwrap(); store.make_available(Data { relay_parent, parachain_id: para_id_2, block_data: block_data_2.clone(), - outgoing_queues: None, }).unwrap(); let candidate_1 = CandidateReceipt { @@ -460,7 +438,6 @@ mod tests { signature: Default::default(), head_data: Default::default(), parent_head: Default::default(), - egress_queue_roots: Vec::new(), fees: 0, block_data_hash: block_data_1.hash(), upward_messages: Vec::new(), @@ -473,7 +450,6 @@ mod tests { signature: Default::default(), head_data: Default::default(), parent_head: Default::default(), - egress_queue_roots: Vec::new(), fees: 0, block_data_hash: block_data_2.hash(), upward_messages: Vec::new(), @@ -516,34 +492,12 @@ mod tests { let para_id = 5.into(); let block_data = BlockData(vec![1, 2, 3]); - let message_queue_root_1 = [0x42; 32].into(); - let message_queue_root_2 = [0x43; 32].into(); - - let message_a = Message(vec![1, 2, 3, 4]); - let message_b = Message(vec![4, 5, 6, 7]); - - let outgoing_queues = AvailableMessages(vec![ - (message_queue_root_1, vec![message_a.clone()]), - (message_queue_root_2, vec![message_b.clone()]), - ]); - let store = Store::new_in_memory(); store.make_available(Data { relay_parent, parachain_id: para_id, - block_data: block_data.clone(), - outgoing_queues: Some(outgoing_queues), + block_data, }).unwrap(); - - assert_eq!( - store.queue_by_root(&message_queue_root_1), - Some(vec![message_a]), - ); - - assert_eq!( - store.queue_by_root(&message_queue_root_2), - Some(vec![message_b]), - ); } #[test] @@ -554,21 +508,10 @@ mod tests { let block_data_hash = block_data.hash(); let n_validators = 5; - let message_queue_root_1 = [0x42; 32].into(); - let message_queue_root_2 = [0x43; 32].into(); - - let message_a = Message(vec![1, 2, 3, 4]); - let message_b = Message(vec![5, 6, 7, 8]); - - let outgoing_queues = Some(AvailableMessages(vec![ - (message_queue_root_1, vec![message_a.clone()]), - (message_queue_root_2, vec![message_b.clone()]), - ])); - let erasure_chunks = erasure::obtain_chunks( n_validators, &block_data, - outgoing_queues.as_ref()).unwrap(); + ).unwrap(); let branches = erasure::branches(erasure_chunks.as_ref()); @@ -578,7 +521,6 @@ mod tests { signature: Default::default(), head_data: Default::default(), parent_head: Default::default(), - egress_queue_roots: Vec::new(), fees: 0, block_data_hash: block_data.hash(), upward_messages: Vec::new(), diff --git a/polkadot/availability-store/src/worker.rs b/polkadot/availability-store/src/worker.rs index f83dc8fe2c..f78416287c 100644 --- a/polkadot/availability-store/src/worker.rs +++ b/polkadot/availability-store/src/worker.rs @@ -35,7 +35,7 @@ use consensus_common::{ use polkadot_primitives::{Block, BlockId, Hash}; use polkadot_primitives::parachain::{ CandidateReceipt, ParachainHost, ValidatorId, - ValidatorPair, AvailableMessages, BlockData, ErasureChunk, + ValidatorPair, ErasureChunk, PoVBlock, }; use futures::{prelude::*, future::select, channel::{mpsc, oneshot}, task::{Spawn, SpawnExt}}; use keystore::KeyStorePtr; @@ -90,7 +90,7 @@ pub(crate) struct ParachainBlocks { /// The relay parent of the block these parachain blocks belong to. pub relay_parent: Hash, /// The blocks themselves. - pub blocks: Vec<(CandidateReceipt, Option<(BlockData, AvailableMessages)>)>, + pub blocks: Vec<(CandidateReceipt, Option)>, /// A sender to signal the result asynchronously. pub result: oneshot::Sender>, } @@ -367,7 +367,7 @@ where runtime_handle: &Handle, sender: &mut mpsc::UnboundedSender, relay_parent: Hash, - blocks: Vec<(CandidateReceipt, Option<(BlockData, AvailableMessages)>)>, + blocks: Vec<(CandidateReceipt, Option)>, ) -> Result<(), Error> { let hashes: Vec<_> = blocks.iter().map(|(c, _)| c.hash()).collect(); @@ -375,7 +375,7 @@ where for (candidate, block) in blocks.into_iter() { let _ = self.availability_store.add_candidate(&candidate); - if let Some((_block, _msgs)) = block { + if let Some(_block) = block { // Should we be breaking block into chunks here and gossiping it and so on? } diff --git a/polkadot/collator/src/lib.rs b/polkadot/collator/src/lib.rs index 9ad8d9a5da..8c91071f93 100644 --- a/polkadot/collator/src/lib.rs +++ b/polkadot/collator/src/lib.rs @@ -48,7 +48,6 @@ use std::collections::HashSet; use std::fmt; use std::sync::Arc; use std::time::Duration; -use std::pin::Pin; use futures::{future, Future, Stream, FutureExt, TryFutureExt, StreamExt, task::Spawn}; use log::warn; @@ -57,18 +56,17 @@ use sp_core::{Pair, Blake2Hasher}; use polkadot_primitives::{ BlockId, Hash, Block, parachain::{ - self, BlockData, DutyRoster, HeadData, ConsolidatedIngress, Message, Id as ParaId, - OutgoingMessages, PoVBlock, Status as ParachainStatus, ValidatorId, CollatorPair, + self, BlockData, DutyRoster, HeadData, Id as ParaId, + PoVBlock, Status as ParachainStatus, ValidatorId, CollatorPair, } }; use polkadot_cli::{ ProvideRuntimeApi, AbstractService, ParachainHost, IsKusama, service::{self, Roles, SelectChain} }; -use polkadot_network::legacy::validation::{LeafWorkParams, ValidationNetwork}; +use polkadot_network::legacy::validation::ValidationNetwork; pub use polkadot_cli::{VersionInfo, load_spec, service::Configuration}; -pub use polkadot_network::legacy::validation::Incoming; pub use polkadot_validation::SignedStatement; pub use polkadot_primitives::parachain::CollatorId; pub use sc_network::PeerId; @@ -111,14 +109,14 @@ pub struct InvalidHead; /// Collation errors. #[derive(Debug)] -pub enum Error { +pub enum Error { /// Error on the relay-chain side of things. - Polkadot(R), + Polkadot(String), /// Error on the collator side of things. Collator(InvalidHead), } -impl fmt::Display for Error { +impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Error::Polkadot(ref err) => write!(f, "Polkadot node error: {}", err), @@ -162,65 +160,41 @@ pub trait BuildParachainContext { /// This can be implemented through an externally attached service or a stub. /// This is expected to be a lightweight, shared type like an Arc. pub trait ParachainContext: Clone { - type ProduceCandidate: Future>; + type ProduceCandidate: Future>; /// Produce a candidate, given the relay parent hash, the latest ingress queue information /// and the last parachain head. - fn produce_candidate>( + fn produce_candidate( &mut self, relay_parent: Hash, status: ParachainStatus, - ingress: I, ) -> Self::ProduceCandidate; } -/// Relay chain context needed to collate. -/// This encapsulates a network and local database which may store -/// some of the input. -pub trait RelayChainContext { - type Error: std::fmt::Debug; - - /// Future that resolves to the un-routed egress queues of a parachain. - /// The first item is the oldest. - type FutureEgress: Future>; - - /// Get un-routed egress queues from a parachain to the local parachain. - fn unrouted_egress(&self, _id: ParaId) -> Self::FutureEgress; -} - /// Produce a candidate for the parachain, with given contexts, parent head, and signing key. -pub async fn collate( +pub async fn collate

( relay_parent: Hash, local_id: ParaId, parachain_status: ParachainStatus, - relay_context: R, mut para_context: P, key: Arc, ) - -> Result<(parachain::Collation, OutgoingMessages), Error> + -> Result where - R: RelayChainContext, P: ParachainContext, P::ProduceCandidate: Send, { - let ingress = relay_context.unrouted_egress(local_id).await.map_err(Error::Polkadot)?; - - let (block_data, head_data, mut outgoing) = para_context.produce_candidate( + let (block_data, head_data) = para_context.produce_candidate( relay_parent, parachain_status, - ingress.0.iter().flat_map(|&(id, ref msgs)| msgs.iter().cloned().map(move |msg| (id, msg))) ).map_err(Error::Collator).await?; let block_data_hash = block_data.hash(); let signature = key.sign(block_data_hash.as_ref()); - let egress_queue_roots = - polkadot_validation::egress_roots(&mut outgoing.outgoing_messages); - let info = parachain::CollationInfo { parachain_index: local_id, collator: key.public(), signature, - egress_queue_roots, head_data, block_data_hash, upward_messages: Vec::new(), @@ -230,47 +204,10 @@ pub async fn collate( info, pov: PoVBlock { block_data, - ingress, }, }; - Ok((collation, outgoing)) -} - -/// Polkadot-api context. -struct ApiContext { - network: Arc>, - parent_hash: Hash, - validators: Vec, -} - -impl RelayChainContext for ApiContext where - P: ProvideRuntimeApi + Send + Sync, - P::Api: ParachainHost, - SP: Spawn + Clone + Send + Sync -{ - type Error = String; - type FutureEgress = Pin> + Send>>; - - fn unrouted_egress(&self, _id: ParaId) -> Self::FutureEgress { - let network = self.network.clone(); - let parent_hash = self.parent_hash; - let authorities = self.validators.clone(); - - async move { - // TODO: https://github.com/paritytech/polkadot/issues/253 - // - // Fetch ingress and accumulate all unrounted egress - let _session = network.instantiate_leaf_work(LeafWorkParams { - local_session_key: None, - parent_hash, - authorities, - }) - .map_err(|e| format!("unable to instantiate validation session: {:?}", e)); - - Ok(ConsolidatedIngress(Vec::new())) - }.boxed() - } + Ok(collation) } /// Run the collator node using the given `service`. @@ -378,7 +315,6 @@ fn run_collator_node( let client = client.clone(); let key = key.clone(); let parachain_context = parachain_context.clone(); - let validation_network = validation_network.clone(); let work = future::lazy(move |_| { let api = client.runtime_api(); @@ -395,27 +331,19 @@ fn run_collator_node( try_fr!(api.duty_roster(&id)), ); - let context = ApiContext { - network: validation_network, - parent_hash: relay_parent, - validators, - }; - let collation_work = collate( relay_parent, para_id, status, - context, parachain_context, key, - ).map_ok(move |(collation, outgoing)| { + ).map_ok(move |collation| { network.with_spec(move |spec, ctx| { let res = spec.add_local_collation( ctx, relay_parent, targets, collation, - outgoing, ); tokio::spawn(res.boxed()); @@ -514,104 +442,26 @@ pub fn run_collator

( #[cfg(test)] mod tests { - use std::collections::HashMap; - use polkadot_primitives::parachain::{TargetedMessage, FeeSchedule}; + use polkadot_primitives::parachain::FeeSchedule; use keyring::Sr25519Keyring; use super::*; - #[derive(Default, Clone)] - struct DummyRelayChainContext { - ingress: HashMap - } - - impl RelayChainContext for DummyRelayChainContext { - type Error = (); - type FutureEgress = Box> + Unpin>; - - fn unrouted_egress(&self, para_id: ParaId) -> Self::FutureEgress { - match self.ingress.get(¶_id) { - Some(ingress) => Box::new(future::ok(ingress.clone())), - None => Box::new(future::pending()), - } - } - } - #[derive(Clone)] struct DummyParachainContext; impl ParachainContext for DummyParachainContext { - type ProduceCandidate = future::Ready>; + type ProduceCandidate = future::Ready>; - fn produce_candidate>( + fn produce_candidate( &mut self, _relay_parent: Hash, _status: ParachainStatus, - ingress: I, ) -> Self::ProduceCandidate { // send messages right back. future::ok(( BlockData(vec![1, 2, 3, 4, 5,]), HeadData(vec![9, 9, 9]), - OutgoingMessages { - outgoing_messages: ingress.into_iter().map(|(id, msg)| TargetedMessage { - target: id, - data: msg.0, - }).collect(), - } )) } } - - #[test] - fn collates_correct_queue_roots() { - let mut context = DummyRelayChainContext::default(); - - let id = ParaId::from(100); - - let a = ParaId::from(123); - let b = ParaId::from(456); - - let messages_from_a = vec![ - Message(vec![1, 1, 1]), - Message(b"helloworld".to_vec()), - ]; - let messages_from_b = vec![ - Message(b"dogglesworth".to_vec()), - Message(b"buy_1_chili_con_carne_here_is_my_cash".to_vec()), - ]; - - let root_a = ::polkadot_validation::message_queue_root( - messages_from_a.iter().map(|msg| &msg.0) - ); - - let root_b = ::polkadot_validation::message_queue_root( - messages_from_b.iter().map(|msg| &msg.0) - ); - - context.ingress.insert(id, ConsolidatedIngress(vec![ - (b, messages_from_b), - (a, messages_from_a), - ])); - - let future = collate( - Default::default(), - id, - ParachainStatus { - head_data: HeadData(vec![5]), - balance: 10, - fee_schedule: FeeSchedule { - base: 0, - per_byte: 1, - }, - }, - context.clone(), - DummyParachainContext, - Arc::new(Sr25519Keyring::Alice.pair().into()), - ); - - let collation = futures::executor::block_on(future).unwrap().0; - - // ascending order by root. - assert_eq!(collation.info.egress_queue_roots, vec![(a, root_a), (b, root_b)]); - } } diff --git a/polkadot/erasure-coding/src/lib.rs b/polkadot/erasure-coding/src/lib.rs index 42dc107f67..0829f38d53 100644 --- a/polkadot/erasure-coding/src/lib.rs +++ b/polkadot/erasure-coding/src/lib.rs @@ -27,7 +27,7 @@ use codec::{Encode, Decode}; use reed_solomon::galois_16::{self, ReedSolomon}; use primitives::{Hash as H256, BlakeTwo256, HashT}; -use primitives::parachain::{BlockData, AvailableMessages}; +use primitives::parachain::BlockData; use sp_core::Blake2Hasher; use trie::{EMPTY_PREFIX, MemoryDB, Trie, TrieMut, trie_types::{TrieDBMut, TrieDB}}; @@ -125,11 +125,11 @@ fn code_params(n_validators: usize) -> Result { /// Obtain erasure-coded chunks, one for each validator. /// /// Works only up to 65536 validators, and `n_validators` must be non-zero. -pub fn obtain_chunks(n_validators: usize, block_data: &BlockData, outgoing: Option<&AvailableMessages>) +pub fn obtain_chunks(n_validators: usize, block_data: &BlockData) -> Result>, Error> { let params = code_params(n_validators)?; - let encoded = (block_data, outgoing).encode(); + let encoded = block_data.encode(); if encoded.is_empty() { return Err(Error::BadPayload); @@ -151,7 +151,7 @@ pub fn obtain_chunks(n_validators: usize, block_data: &BlockData, outgoing: Opti /// /// Works only up to 65536 validators, and `n_validators` must be non-zero. pub fn reconstruct<'a, I: 'a>(n_validators: usize, chunks: I) - -> Result<(BlockData, Option), Error> + -> Result where I: IntoIterator { let params = code_params(n_validators)?; @@ -402,11 +402,9 @@ mod tests { #[test] fn round_trip_block_data() { let block_data = BlockData((0..255).collect()); - let ex = Some(AvailableMessages(Vec::new())); let chunks = obtain_chunks( 10, &block_data, - ex.as_ref(), ).unwrap(); assert_eq!(chunks.len(), 10); @@ -422,18 +420,16 @@ mod tests { ].iter().cloned(), ).unwrap(); - assert_eq!(reconstructed, (block_data, ex)); + assert_eq!(reconstructed, block_data); } #[test] fn construct_valid_branches() { let block_data = BlockData(vec![2; 256]); - let ex = Some(AvailableMessages(Vec::new())); let chunks = obtain_chunks( 10, &block_data, - ex.as_ref(), ).unwrap(); assert_eq!(chunks.len(), 10); diff --git a/polkadot/network/src/legacy/collator_pool.rs b/polkadot/network/src/legacy/collator_pool.rs index e13b2dc8fd..4ca1d03711 100644 --- a/polkadot/network/src/legacy/collator_pool.rs +++ b/polkadot/network/src/legacy/collator_pool.rs @@ -236,15 +236,12 @@ impl CollatorPool { mod tests { use super::*; use sp_core::crypto::UncheckedInto; - use polkadot_primitives::parachain::{ - CandidateReceipt, BlockData, PoVBlock, HeadData, ConsolidatedIngress, - }; + use polkadot_primitives::parachain::{CandidateReceipt, BlockData, PoVBlock, HeadData}; use futures::executor::block_on; fn make_pov(block_data: Vec) -> PoVBlock { PoVBlock { block_data: BlockData(block_data), - ingress: ConsolidatedIngress(Vec::new()), } } @@ -294,7 +291,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: [3; 32].into(), upward_messages: Vec::new(), @@ -324,7 +320,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: [3; 32].into(), upward_messages: Vec::new(), diff --git a/polkadot/network/src/legacy/gossip/attestation.rs b/polkadot/network/src/legacy/gossip/attestation.rs index ad7c4e7705..e019859695 100644 --- a/polkadot/network/src/legacy/gossip/attestation.rs +++ b/polkadot/network/src/legacy/gossip/attestation.rs @@ -93,11 +93,6 @@ impl PeerData { pub(super) fn knowledge_at_mut(&mut self, parent_hash: &Hash) -> Option<&mut Knowledge> { self.live.get_mut(parent_hash) } - - /// Get an iterator over all live leaves of this peer. - pub(super) fn leaves(&self) -> impl Iterator { - self.live.keys() - } } /// An impartial view of what topics and data are valid based on attestation session data. diff --git a/polkadot/network/src/legacy/gossip/message_routing.rs b/polkadot/network/src/legacy/gossip/message_routing.rs deleted file mode 100644 index 66debb945e..0000000000 --- a/polkadot/network/src/legacy/gossip/message_routing.rs +++ /dev/null @@ -1,339 +0,0 @@ -// Copyright 2019-2020 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 . - -//! Data structures and synchronous logic for ICMP message gossip. -//! -//! The parent-module documentation describes some rationale of the general -//! gossip protocol design. -//! -//! The ICMP message-routing gossip works according to those rationale. -//! -//! In this protocol, we perform work under 4 conditions: -//! ### 1. Upon observation of a new leaf in the block-DAG. -//! -//! We first communicate the best leaves to our neighbors in the gossip graph -//! by the means of a neighbor packet. Then, we query to discover the trie roots -//! of all un-routed message queues from the perspective of each of those leaves. -//! -//! For any trie root in the unrouted set for the new leaf, if we have the corresponding -//! queue, we send it to any peers with the new leaf in their latest advertised set. -//! -//! Which parachain those messages go to and from is unimportant, because this is -//! an everybody-sees-everything style protocol. The only important property is "liveness": -//! that the queue root is un-routed at one of the leaves we perceive to be at the head -//! of the block-DAG. -//! -//! In Substrate gossip, every message is associated with a topic. Typically, -//! many messages are grouped under a single topic. In this gossip system, each queue -//! gets its own topic, which is based on the root hash of the queue. This is because -//! many different chain leaves may have the same queue as un-routed, so it's better than -//! attempting to group message packets by the leaf they appear unrouted at. -//! -//! ### 2. Upon a neighbor packet from a peer. -//! -//! The neighbor packet from a peer should contain perceived chain heads of that peer. -//! If there is any overlap between our perceived chain heads and theirs, we send -//! them any known, un-routed message queue from either set. -//! -//! ### 3. Upon receiving a message queue from a peer. -//! -//! If the message queue is in the un-routed set of one of the latest leaves we've updated to, -//! we accept it and relay to any peers who need that queue as well. -//! -//! If not, we report the peer to the peer-set manager for sending us bad data. -//! -//! ### 4. Periodic Pruning -//! -//! We prune messages that are not un-routed from the view of any leaf and cease -//! to attempt to send them to any peer. - -use sp_runtime::traits::{BlakeTwo256, Hash as HashT}; -use polkadot_primitives::Hash; -use std::collections::{HashMap, HashSet}; -use sp_blockchain::Error as ClientError; -use super::{MAX_CHAIN_HEADS, GossipValidationResult, LeavesVec, ChainContext}; - -/// Construct a topic for a message queue root deterministically. -pub fn queue_topic(queue_root: Hash) -> Hash { - let mut v = queue_root.as_ref().to_vec(); - v.extend(b"message_queue"); - - BlakeTwo256::hash(&v[..]) -} - -/// A view of which queue roots are current for a given set of leaves. -#[derive(Default)] -pub struct View { - leaves: LeavesVec, - leaf_topics: HashMap>, // leaf_hash -> { topics } - expected_queues: HashMap, // topic -> (queue-root, known) -} - -impl View { - /// Update the set of current leaves. This is called when we perceive a new bset leaf-set. - pub fn update_leaves(&mut self, context: &T, new_leaves: I) - -> Result<(), ClientError> - where I: Iterator - { - let new_leaves = new_leaves.take(MAX_CHAIN_HEADS); - let old_leaves = std::mem::replace(&mut self.leaves, new_leaves.collect()); - - let expected_queues = &mut self.expected_queues; - let leaves = &self.leaves; - self.leaf_topics.retain(|l, topics| { - if leaves.contains(l) { return true } - - // prune out all data about old leaves we don't follow anymore. - for topic in topics.iter() { - expected_queues.remove(topic); - } - false - }); - - let mut res = Ok(()); - - // add in new data about fresh leaves. - for new_leaf in &self.leaves { - if old_leaves.contains(new_leaf) { continue } - - let mut this_leaf_topics = HashSet::new(); - - let r = context.leaf_unrouted_roots(new_leaf, &mut |&queue_root| { - let topic = queue_topic(queue_root); - this_leaf_topics.insert(topic); - expected_queues.entry(topic).or_insert((queue_root, false)); - }); - - if r.is_err() { - if let Err(e) = res { - log::debug!(target: "message_routing", "Ignored duplicate error {}", e) - }; - res = r; - } - - self.leaf_topics.insert(*new_leaf, this_leaf_topics); - } - - res - } - - /// Validate an incoming message queue against this view. If it is accepted - /// by our view of un-routed message queues, we will keep and re-propagate. - pub fn validate_queue_and_note_known(&mut self, messages: &super::GossipParachainMessages) - -> (GossipValidationResult, sc_network::ReputationChange) - { - let ostensible_topic = queue_topic(messages.queue_root); - match self.expected_queues.get_mut(&ostensible_topic) { - None => (GossipValidationResult::Discard, super::cost::UNNEEDED_ICMP_MESSAGES), - Some(&mut (_, ref mut known)) => { - if !messages.queue_root_is_correct() { - ( - GossipValidationResult::Discard, - super::cost::icmp_messages_root_mismatch(messages.messages.len()), - ) - } else { - *known = true; - ( - GossipValidationResult::ProcessAndKeep(ostensible_topic), - super::benefit::NEW_ICMP_MESSAGES, - ) - } - } - } - } - - /// Whether a message with given topic is live. - pub fn is_topic_live(&self, topic: &Hash) -> bool { - self.expected_queues.get(topic).is_some() - } - - /// Whether a message is allowed under the intersection of the given leaf-set - /// and our own. - pub fn allowed_intersecting(&self, other_leaves: &LeavesVec, topic: &Hash) -> bool { - for i in other_leaves { - for j in &self.leaves { - if i == j { - let leaf_topics = self.leaf_topics.get(i) - .expect("leaf_topics are mutated only in update_leaves; \ - we have an entry for each item in self.leaves; \ - i is in self.leaves; qed"); - - if leaf_topics.contains(topic) { - return true; - } - } - } - } - - false - } - - /// Get topics of all message queues a peer is interested in - this is useful - /// when a peer has informed us of their new best leaves. - pub fn intersection_topics(&self, other_leaves: &LeavesVec) -> impl Iterator { - let deduplicated = other_leaves.iter() - .filter_map(|l| self.leaf_topics.get(l)) - .flat_map(|topics| topics.iter().cloned()) - .collect::>(); - - deduplicated.into_iter() - } - - /// Iterate over all live message queues for which the data is marked as not locally known, - /// calling a closure with `(topic, root)`. The closure will return whether the queue data is - /// unknown. - /// - /// This is called when we should send un-routed message queues that we are - /// newly aware of to peers - as in when we update our leaves. - pub fn sweep_unknown_queues(&mut self, mut check_known: impl FnMut(&Hash, &Hash) -> bool) { - for (topic, &mut (ref queue_root, ref mut known)) in self.expected_queues.iter_mut() { - if !*known { - *known = check_known(topic, queue_root) - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::legacy::tests::TestChainContext; - use crate::legacy::gossip::{Known, GossipParachainMessages}; - use polkadot_primitives::parachain::Message as ParachainMessage; - - fn hash(x: u8) -> Hash { - [x; 32].into() - } - - fn message_queue(from: u8, to: u8) -> Option<[[u8; 2]; 1]> { - if from == to { - None - } else { - Some([[from, to]]) - } - } - - fn message_queue_root(from: u8, to: u8) -> Option { - message_queue(from, to).map( - |q| polkadot_validation::message_queue_root(q.iter()) - ) - } - - // check that our view has all of the roots of the message queues - // emitted in the heads identified in `our_heads`, and none of the others. - fn check_roots(view: &mut View, our_heads: &[u8], n_heads: u8) -> bool { - for i in 0..n_heads { - for j in 0..n_heads { - if let Some(messages) = message_queue(i, j) { - let queue_root = message_queue_root(i, j).unwrap(); - let messages = GossipParachainMessages { - queue_root, - messages: messages.iter().map(|m| ParachainMessage(m.to_vec())).collect(), - }; - - let had_queue = match view.validate_queue_and_note_known(&messages).0 { - GossipValidationResult::ProcessAndKeep(topic) => topic == queue_topic(queue_root), - _ => false, - }; - - if our_heads.contains(&i) != had_queue { - return false - } - } - } - } - - true - } - - #[test] - fn update_leaves_none_in_common() { - let mut ctx = TestChainContext::default(); - let n_heads = 5; - - for i in 0..n_heads { - ctx.known_map.insert(hash(i as u8), Known::Leaf); - - let messages_out: Vec<_> = (0..n_heads).filter_map(|j| message_queue_root(i, j)).collect(); - - if !messages_out.is_empty() { - ctx.ingress_roots.insert(hash(i as u8), messages_out); - } - } - - // initialize the view with 2 leaves. - - let mut view = View::default(); - view.update_leaves( - &ctx, - [hash(0), hash(1)].iter().cloned(), - ).unwrap(); - - // we should have all queue roots that were - // un-routed from the perspective of those 2 - // leaves and no others. - - assert!(check_roots(&mut view, &[0, 1], n_heads)); - - // after updating to a disjoint set, - // the property that we are aware of all un-routed - // from the perspective of our known leaves should - // remain the same. - - view.update_leaves( - &ctx, - [hash(2), hash(3), hash(4)].iter().cloned(), - ).unwrap(); - - assert!(check_roots(&mut view, &[2, 3, 4], n_heads)); - } - - #[test] - fn update_leaves_overlapping() { - let mut ctx = TestChainContext::default(); - let n_heads = 5; - - for i in 0..n_heads { - ctx.known_map.insert(hash(i as u8), Known::Leaf); - - let messages_out: Vec<_> = (0..n_heads).filter_map(|j| message_queue_root(i, j)).collect(); - - if !messages_out.is_empty() { - ctx.ingress_roots.insert(hash(i as u8), messages_out); - } - } - - let mut view = View::default(); - view.update_leaves( - &ctx, - [hash(0), hash(1), hash(2)].iter().cloned(), - ).unwrap(); - - assert!(check_roots(&mut view, &[0, 1, 2], n_heads)); - - view.update_leaves( - &ctx, - [hash(2), hash(3), hash(4)].iter().cloned(), - ).unwrap(); - - // after updating to a leaf-set overlapping with the prior, - // the property that we are aware of all un-routed - // from the perspective of our known leaves should - // remain the same. - - assert!(check_roots(&mut view, &[2, 3, 4], n_heads)); - } -} diff --git a/polkadot/network/src/legacy/gossip/mod.rs b/polkadot/network/src/legacy/gossip/mod.rs index 078131847b..f4800bcb5f 100644 --- a/polkadot/network/src/legacy/gossip/mod.rs +++ b/polkadot/network/src/legacy/gossip/mod.rs @@ -49,7 +49,7 @@ //! Peers who send information which was not allowed under a recent neighbor packet //! will be noted as non-beneficial to Substrate's peer-set management utility. -use sp_runtime::{generic::BlockId, traits::{BlakeTwo256, Hash as HashT}}; +use sp_runtime::traits::{BlakeTwo256, Hash as HashT}; use sp_blockchain::Error as ClientError; use sc_network::{config::Roles, Context, PeerId, ReputationChange}; use sc_network::{NetworkService as SubstrateNetworkService, specialization::NetworkSpecialization}; @@ -60,7 +60,7 @@ use sc_network_gossip::{ use polkadot_validation::{SignedStatement}; use polkadot_primitives::{Block, Hash}; use polkadot_primitives::parachain::{ - ParachainHost, ValidatorId, Message as ParachainMessage, ErasureChunk as PrimitiveChunk + ParachainHost, ValidatorId, ErasureChunk as PrimitiveChunk }; use polkadot_erasure_coding::{self as erasure}; use codec::{Decode, Encode}; @@ -72,15 +72,12 @@ use std::sync::Arc; use arrayvec::ArrayVec; use futures::prelude::*; use parking_lot::RwLock; -use log::warn; use crate::legacy::{GossipMessageStream, NetworkService, GossipService, PolkadotProtocol, router::attestation_topic}; use attestation::{View as AttestationView, PeerData as AttestationPeerData}; -use message_routing::{View as MessageRoutingView}; mod attestation; -mod message_routing; /// The engine ID of the polkadot attestation system. pub const POLKADOT_ENGINE_ID: sp_runtime::ConsensusEngineId = *b"dot1"; @@ -99,8 +96,6 @@ mod benefit { pub const NEW_ATTESTATION: Rep = Rep::new(50, "Polkadot: New attestation"); /// When a peer sends us a previously-unknown erasure chunk. pub const NEW_ERASURE_CHUNK: Rep = Rep::new(10, "Polkadot: New erasure chunk"); - /// When a peer sends us a previously-unknown message packet. - pub const NEW_ICMP_MESSAGES: Rep = Rep::new(50, "Polkadot: New ICMP messages"); } mod cost { @@ -119,19 +114,10 @@ mod cost { pub const BAD_SIGNATURE: Rep = Rep::new(-500, "Polkadot: Bad signature"); /// A peer sent us a bad neighbor packet. pub const BAD_NEIGHBOR_PACKET: Rep = Rep::new(-300, "Polkadot: Bad neighbor"); - /// A peer sent us an ICMP queue we haven't advertised a need for. - pub const UNNEEDED_ICMP_MESSAGES: Rep = Rep::new(-100, "Polkadot: Unexpected ICMP message"); /// A peer sent us an erasure chunk referring to a candidate that we are not aware of. pub const ORPHANED_ERASURE_CHUNK: Rep = Rep::new(-10, "An erasure chunk from unknown candidate"); /// A peer sent us an erasure chunk that does not match candidate's erasure root. pub const ERASURE_CHUNK_WRONG_ROOT: Rep = Rep::new(-100, "Chunk doesn't match encoding root"); - - /// A peer sent us an ICMP queue with a bad root. - pub fn icmp_messages_root_mismatch(n_messages: usize) -> Rep { - const PER_MESSAGE: i32 = -150; - - Rep::new((0..n_messages).map(|_| PER_MESSAGE).sum(), "Polkadot: ICMP root mismatch") - } } /// A gossip message. @@ -144,12 +130,9 @@ pub enum GossipMessage { /// Non-candidate statements should only be sent to peers who are aware of the candidate. #[codec(index = "2")] Statement(GossipStatement), - /// A packet of messages from one parachain to another. - #[codec(index = "3")] - ParachainMessages(GossipParachainMessages), // TODO: https://github.com/paritytech/polkadot/issues/253 /// A packet containing one of the erasure-coding chunks of one candidate. - #[codec(index = "4")] + #[codec(index = "3")] ErasureChunk(ErasureChunkMessage), } @@ -165,12 +148,6 @@ impl From for GossipMessage { } } -impl From for GossipMessage { - fn from(messages: GossipParachainMessages) -> Self { - GossipMessage::ParachainMessages(messages) - } -} - /// A gossip message containing a statement. #[derive(Encode, Decode, Clone, PartialEq)] pub struct GossipStatement { @@ -218,19 +195,6 @@ impl From for GossipMessage { pub struct GossipParachainMessages { /// The root of the message queue. pub queue_root: Hash, - /// The messages themselves. - pub messages: Vec, -} - -impl GossipParachainMessages { - // confirms that the queue-root in the struct correctly matches - // the messages. - fn queue_root_is_correct(&self) -> bool { - let root = polkadot_validation::message_queue_root( - self.messages.iter().map(|m| &m.0) - ); - root == self.queue_root - } } /// A versioned neighbor message. @@ -283,23 +247,9 @@ impl ChainContext for (F, P) where fn leaf_unrouted_roots( &self, - &leaf: &Hash, - with_queue_root: &mut dyn FnMut(&Hash), + _leaf: &Hash, + _with_queue_root: &mut dyn FnMut(&Hash), ) -> Result<(), ClientError> { - let api = self.1.runtime_api(); - - let leaf_id = BlockId::Hash(leaf); - let active_parachains = api.active_parachains(&leaf_id)?; - - // TODO: https://github.com/paritytech/polkadot/issues/467 - for (para_id, _) in active_parachains { - if let Some(ingress) = api.ingress(&leaf_id, para_id, None)? { - for (_height, _from, queue_root) in ingress.iter() { - with_queue_root(queue_root); - } - } - } - Ok(()) } } @@ -325,7 +275,6 @@ pub fn register_validator gossip.send_message(who, message), - NewLeafAction::Multicast(topic, message) - => gossip.gossip_message(topic, message), } } } @@ -428,7 +373,6 @@ impl> RegisteredMessageValidator { &self, relay_chain_leaf: Hash, validation: MessageValidationData, - lookup_queue_by_root: impl Fn(&Hash) -> Option>, ) -> NewLeafActions { // add an entry in attestation_view // prune any entries from attestation_view which are no longer leaves @@ -441,7 +385,6 @@ impl> RegisteredMessageValidator { let &mut Inner { ref chain, ref mut attestation_view, - ref mut message_routing_view, .. } = &mut *inner; @@ -449,10 +392,6 @@ impl> RegisteredMessageValidator { Some(Known::Leaf) => true, _ => false, }); - - if let Err(e) = message_routing_view.update_leaves(chain, attestation_view.neighbor_info()) { - warn!("Unable to fully update leaf-state: {:?}", e); - } } @@ -461,23 +400,6 @@ impl> RegisteredMessageValidator { |who, message| actions.push(NewLeafAction::TargetedMessage(who.clone(), message)) ); - // feed any new unrouted queues into the propagation pool. - inner.message_routing_view.sweep_unknown_queues(|topic, queue_root| - match lookup_queue_by_root(queue_root) { - Some(messages) => { - let message = GossipMessage::from(GossipParachainMessages { - queue_root: *queue_root, - messages, - }); - - actions.push(NewLeafAction::Multicast(*topic, message)); - - true - } - None => false, - } - ); - NewLeafActions { actions } } @@ -575,16 +497,9 @@ struct PeerData { attestation: AttestationPeerData, } -impl PeerData { - fn leaves(&self) -> impl Iterator { - self.attestation.leaves() - } -} - struct Inner { peers: HashMap, attestation_view: AttestationView, - message_routing_view: MessageRoutingView, availability_store: Option, chain: C, } @@ -602,11 +517,7 @@ impl Inner { let new_leaves = peer.attestation.update_leaves(&chain_heads); let new_attestation_topics = new_leaves.iter().cloned().map(attestation_topic); - // find all topics which are from the intersection of our leaves with the peer's - // new leaves. - let new_message_routing_topics = self.message_routing_view.intersection_topics(&new_leaves); - - new_attestation_topics.chain(new_message_routing_topics).collect() + new_attestation_topics.collect() } else { Vec::new() }; @@ -692,7 +603,6 @@ impl MessageValidator { inner: RwLock::new(Inner { peers: HashMap::new(), attestation_view: Default::default(), - message_routing_view: Default::default(), availability_store: None, chain, }), @@ -740,18 +650,6 @@ impl sc_network_gossip::Validator for MessageVa } (res, cb) } - Ok(GossipMessage::ParachainMessages(messages)) => { - let (res, cb) = { - let mut inner = self.inner.write(); - let inner = &mut *inner; - inner.message_routing_view.validate_queue_and_note_known(&messages) - }; - - if let GossipValidationResult::ProcessAndKeep(ref topic) = res { - context.broadcast_message(topic.clone(), data.to_vec(), false); - } - (res, cb) - } Ok(GossipMessage::ErasureChunk(chunk)) => { self.inner.write().validate_erasure_chunk_packet(chunk) } @@ -767,8 +665,7 @@ impl sc_network_gossip::Validator for MessageVa Box::new(move |topic, _data| { // check that messages from this topic are considered live by one of our protocols. // everything else is expired - let live = inner.attestation_view.is_topic_live(&topic) - || !inner.message_routing_view.is_topic_live(&topic); + let live = inner.attestation_view.is_topic_live(&topic); !live // = expired }) @@ -780,7 +677,6 @@ impl sc_network_gossip::Validator for MessageVa let &mut Inner { ref mut peers, ref mut attestation_view, - ref mut message_routing_view, .. } = &mut *inner; @@ -806,13 +702,6 @@ impl sc_network_gossip::Validator for MessageVa ) }) } - Ok(GossipMessage::ParachainMessages(_)) => match peer { - None => false, - Some(peer) => { - let their_leaves: LeavesVec = peer.leaves().cloned().collect(); - message_routing_view.allowed_intersecting(&their_leaves, topic) - } - } _ => false, } }) @@ -827,9 +716,8 @@ mod tests { use parking_lot::Mutex; use polkadot_primitives::parachain::{CandidateReceipt, HeadData}; use sp_core::crypto::UncheckedInto; - use sp_core::sr25519::{Public as Sr25519Public, Signature as Sr25519Signature}; + use sp_core::sr25519::Signature as Sr25519Signature; use polkadot_validation::GenericStatement; - use super::message_routing::queue_topic; use crate::legacy::tests::TestChainContext; @@ -867,22 +755,6 @@ mod tests { } } - impl NewLeafActions { - fn has_message(&self, who: PeerId, message: GossipMessage) -> bool { - let x = NewLeafAction::TargetedMessage(who, message); - self.actions.iter().find(|&m| m == &x).is_some() - } - - fn has_multicast(&self, topic: Hash, message: GossipMessage) -> bool { - let x = NewLeafAction::Multicast(topic, message); - self.actions.iter().find(|&m| m == &x).is_some() - } - } - - fn validator_id(raw: [u8; 32]) -> ValidatorId { - Sr25519Public::from_raw(raw).into() - } - #[test] fn message_allowed() { let (tx, _rx) = mpsc::channel(); @@ -933,7 +805,6 @@ mod tests { head_data: HeadData(vec![9, 9, 9]), parent_head: HeadData(vec![]), signature: Default::default(), - egress_queue_roots: Vec::new(), fees: 1_000_000, block_data_hash: [20u8; 32].into(), upward_messages: Vec::new(), @@ -1095,12 +966,6 @@ mod tests { let hash_a = [1u8; 32].into(); let root_a = [11u8; 32].into(); - let root_a_topic = queue_topic(root_a); - - let root_a_messages = vec![ - ParachainMessage(vec![1, 2, 3]), - ParachainMessage(vec![4, 5, 6]), - ]; let chain = { let mut chain = TestChainContext::default(); @@ -1111,8 +976,6 @@ mod tests { let validator = RegisteredMessageValidator::new_test(chain, report_handle); - let authorities: Vec = vec![validator_id([0; 32]), validator_id([10; 32])]; - let peer_a = PeerId::random(); let peer_b = PeerId::random(); @@ -1144,274 +1007,5 @@ mod tests { ], ); } - - // ensure that we attempt to multicast all relevant queues after noting a leaf. - { - let actions = validator.new_local_leaf( - hash_a, - MessageValidationData { authorities }, - |root| if root == &root_a { - Some(root_a_messages.clone()) - } else { - None - }, - ); - - assert!(actions.has_message(peer_a.clone(), GossipMessage::from(NeighborPacket { - chain_heads: vec![hash_a], - }))); - - assert!(actions.has_multicast(root_a_topic, GossipMessage::from(GossipParachainMessages { - queue_root: root_a, - messages: root_a_messages.clone(), - }))); - } - - // ensure that we are allowed to multicast to a peer with same chain head, - // but not to one without. - { - let message = GossipMessage::from(GossipParachainMessages { - queue_root: root_a, - messages: root_a_messages.clone(), - }).encode(); - - let mut allowed = validator.inner.message_allowed(); - let intent = MessageIntent::Broadcast; - assert!(allowed(&peer_a, intent, &root_a_topic, &message[..])); - assert!(!allowed(&peer_b, intent, &root_a_topic, &message[..])); - } - } - - #[test] - fn multicasts_icmp_queues_on_neighbor_update() { - let (tx, _rx) = mpsc::channel(); - let tx = Mutex::new(tx); - let report_handle = Box::new(move |peer: &PeerId, cb: ReputationChange| tx.lock().send((peer.clone(), cb)).unwrap()); - - let hash_a = [1u8; 32].into(); - let root_a = [11u8; 32].into(); - let root_a_topic = queue_topic(root_a); - - let root_a_messages = vec![ - ParachainMessage(vec![1, 2, 3]), - ParachainMessage(vec![4, 5, 6]), - ]; - - let chain = { - let mut chain = TestChainContext::default(); - chain.known_map.insert(hash_a, Known::Leaf); - chain.ingress_roots.insert(hash_a, vec![root_a]); - chain - }; - - let validator = RegisteredMessageValidator::new_test(chain, report_handle); - - let authorities: Vec = vec![validator_id([0; 32]), validator_id([10; 32])]; - - let peer_a = PeerId::random(); - let peer_b = PeerId::random(); - - let mut validator_context = MockValidatorContext::default(); - validator.inner.new_peer(&mut validator_context, &peer_a, Roles::FULL); - validator.inner.new_peer(&mut validator_context, &peer_b, Roles::FULL); - assert!(validator_context.events.is_empty()); - validator_context.clear(); - - // ensure that we attempt to multicast all relevant queues after noting a leaf. - { - let actions = validator.new_local_leaf( - hash_a, - MessageValidationData { authorities }, - |root| if root == &root_a { - Some(root_a_messages.clone()) - } else { - None - }, - ); - - assert!(actions.has_message(peer_a.clone(), GossipMessage::from(NeighborPacket { - chain_heads: vec![hash_a], - }))); - - assert!(actions.has_multicast(root_a_topic, GossipMessage::from(GossipParachainMessages { - queue_root: root_a, - messages: root_a_messages.clone(), - }))); - } - - // ensure that we are not allowed to multicast to either peer, as they - // don't have the chain head. - { - let message = GossipMessage::from(GossipParachainMessages { - queue_root: root_a, - messages: root_a_messages.clone(), - }); - - let mut allowed = validator.inner.message_allowed(); - let intent = MessageIntent::Broadcast; - assert!(!allowed(&peer_a, intent, &root_a_topic, &message.encode())); - assert!(!allowed(&peer_b, intent, &root_a_topic, &message.encode())); - } - - // peer A gets updated to the chain head. now we'll attempt to broadcast - // all queues to it. - { - let message = GossipMessage::from(NeighborPacket { - chain_heads: vec![hash_a], - }).encode(); - let res = validator.inner.validate( - &mut validator_context, - &peer_a, - &message[..], - ); - - match res { - GossipValidationResult::Discard => {}, - _ => panic!("wrong result"), - } - assert_eq!( - validator_context.events, - vec![ - ContextEvent::SendTopic(peer_a.clone(), attestation_topic(hash_a), false), - ContextEvent::SendTopic(peer_a.clone(), root_a_topic, false), - ], - ); - } - - // ensure that we are allowed to multicast to a peer with same chain head, - // but not to one without. - { - let message = GossipMessage::from(GossipParachainMessages { - queue_root: root_a, - messages: root_a_messages.clone(), - }).encode(); - - let mut allowed = validator.inner.message_allowed(); - let intent = MessageIntent::Broadcast; - assert!(allowed(&peer_a, intent, &root_a_topic, &message[..])); - assert!(!allowed(&peer_b, intent, &root_a_topic, &message[..])); - } - } - - #[test] - fn accepts_needed_unknown_icmp_message_queue() { - let (tx, _rx) = mpsc::channel(); - let tx = Mutex::new(tx); - let report_handle = Box::new(move |peer: &PeerId, cb: ReputationChange| tx.lock().send((peer.clone(), cb)).unwrap()); - - let hash_a = [1u8; 32].into(); - let root_a_messages = vec![ - ParachainMessage(vec![1, 2, 3]), - ParachainMessage(vec![4, 5, 6]), - ]; - let not_root_a_messages = vec![ - ParachainMessage(vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1]), - ParachainMessage(vec![4, 5, 6]), - ]; - - let root_a = polkadot_validation::message_queue_root( - root_a_messages.iter().map(|m| &m.0) - ); - let not_root_a = [69u8; 32].into(); - let root_a_topic = queue_topic(root_a); - - let chain = { - let mut chain = TestChainContext::default(); - chain.known_map.insert(hash_a, Known::Leaf); - chain.ingress_roots.insert(hash_a, vec![root_a]); - chain - }; - - let validator = RegisteredMessageValidator::new_test(chain, report_handle); - - let authorities: Vec = vec![validator_id([0; 32]), validator_id([10; 32])]; - - let peer_a = PeerId::random(); - let mut validator_context = MockValidatorContext::default(); - - validator.inner.new_peer(&mut validator_context, &peer_a, Roles::FULL); - assert!(validator_context.events.is_empty()); - validator_context.clear(); - - let queue_messages = GossipMessage::from(GossipParachainMessages { - queue_root: root_a, - messages: root_a_messages.clone(), - }); - - let not_queue_messages = GossipMessage::from(GossipParachainMessages { - queue_root: root_a, - messages: not_root_a_messages.clone(), - }); - - let queue_messages_wrong_root = GossipMessage::from(GossipParachainMessages { - queue_root: not_root_a, - messages: root_a_messages.clone(), - }); - - // ensure that we attempt to multicast all relevant queues after noting a leaf. - { - let actions = validator.new_local_leaf( - hash_a, - MessageValidationData { authorities }, - |_root| None, - ); - - assert!(actions.has_message(peer_a.clone(), GossipMessage::from(NeighborPacket { - chain_heads: vec![hash_a], - }))); - - // we don't know this queue! no broadcast :( - assert!(!actions.has_multicast(root_a_topic, queue_messages.clone())); - } - - // rejects right queue with unknown root. - { - let res = validator.inner.validate( - &mut validator_context, - &peer_a, - &queue_messages_wrong_root.encode(), - ); - - match res { - GossipValidationResult::Discard => {}, - _ => panic!("wrong result"), - } - - assert_eq!(validator_context.events, Vec::new()); - } - - // rejects bad queue. - { - let res = validator.inner.validate( - &mut validator_context, - &peer_a, - ¬_queue_messages.encode(), - ); - - match res { - GossipValidationResult::Discard => {}, - _ => panic!("wrong result"), - } - - assert_eq!(validator_context.events, Vec::new()); - } - - // accepts the right queue. - { - let res = validator.inner.validate( - &mut validator_context, - &peer_a, - &queue_messages.encode(), - ); - - match res { - GossipValidationResult::ProcessAndKeep(topic) if topic == root_a_topic => {}, - _ => panic!("wrong result"), - } - - assert_eq!(validator_context.events, vec![ - ContextEvent::BroadcastMessage(root_a_topic, queue_messages.encode(), false), - ]); - } } } diff --git a/polkadot/network/src/legacy/mod.rs b/polkadot/network/src/legacy/mod.rs index 553cc8ff36..413a5d4b82 100644 --- a/polkadot/network/src/legacy/mod.rs +++ b/polkadot/network/src/legacy/mod.rs @@ -31,7 +31,7 @@ use futures::prelude::*; use polkadot_primitives::{Block, Hash, Header}; use polkadot_primitives::parachain::{ Id as ParaId, CollatorId, CandidateReceipt, Collation, PoVBlock, - StructuredUnroutedIngress, ValidatorId, OutgoingMessages, ErasureChunk, + ValidatorId, ErasureChunk, }; use sc_network::{ PeerId, RequestId, Context, StatusMessage as GenericFullStatus, @@ -169,7 +169,6 @@ struct PoVBlockRequest { candidate_hash: Hash, block_data_hash: Hash, sender: oneshot::Sender, - canon_roots: StructuredUnroutedIngress, } impl PoVBlockRequest { @@ -182,13 +181,7 @@ impl PoVBlockRequest { return Err(self); } - match polkadot_validation::validate_incoming(&self.canon_roots, &pov_block.ingress) { - Ok(()) => { - let _ = self.sender.send(pov_block); - Ok(()) - } - Err(_) => Err(self) - } + Ok(()) } } @@ -300,7 +293,6 @@ impl PolkadotProtocol { ctx: &mut dyn Context, candidate: &CandidateReceipt, relay_parent: Hash, - canon_roots: StructuredUnroutedIngress, ) -> oneshot::Receiver { let (tx, rx) = oneshot::channel(); @@ -310,7 +302,6 @@ impl PolkadotProtocol { candidate_hash: candidate.hash(), block_data_hash: candidate.block_data_hash, sender: tx, - canon_roots, }); self.dispatch_pending_requests(ctx); @@ -617,7 +608,6 @@ impl Specialization for PolkadotProtocol { validation_leaf: Default::default(), candidate_hash: Default::default(), block_data_hash: Default::default(), - canon_roots: StructuredUnroutedIngress(Vec::new()), sender, })); } @@ -747,7 +737,6 @@ impl PolkadotProtocol { relay_parent: Hash, targets: HashSet, collation: Collation, - outgoing_targeted: OutgoingMessages, ) -> impl Future { debug!(target: "p_net", "Importing local collation on relay parent {:?} and parachain {:?}", relay_parent, collation.info.parachain_index); @@ -776,7 +765,6 @@ impl PolkadotProtocol { relay_parent, parachain_id: collation_cloned.info.parachain_index, block_data: collation_cloned.pov.block_data.clone(), - outgoing_queues: Some(outgoing_targeted.clone().into()), }).await; } } diff --git a/polkadot/network/src/legacy/router.rs b/polkadot/network/src/legacy/router.rs index 6171ca6729..4a969a4870 100644 --- a/polkadot/network/src/legacy/router.rs +++ b/polkadot/network/src/legacy/router.rs @@ -29,7 +29,7 @@ use polkadot_validation::{ }; use polkadot_primitives::{Block, Hash}; use polkadot_primitives::parachain::{ - OutgoingMessages, CandidateReceipt, ParachainHost, ValidatorIndex, Collation, PoVBlock, ErasureChunk, + CandidateReceipt, ParachainHost, ValidatorIndex, Collation, PoVBlock, ErasureChunk, }; use sp_api::ProvideRuntimeApi; @@ -203,9 +203,8 @@ impl + Send + Sync + 'static, T> Router where Ok(validated) => { // store the data before broadcasting statements, so other peers can fetch. knowledge.lock().note_candidate( - candidate_hash, - Some(validated.0.pov_block().clone()), - validated.0.outgoing_messages().cloned(), + candidate_hash, + Some(validated.0.pov_block().clone()), ); // propagate the statement. @@ -241,7 +240,6 @@ impl + Send, T> TableRouter for Router where &self, collation: Collation, receipt: CandidateReceipt, - outgoing: OutgoingMessages, chunks: (ValidatorIndex, &[ErasureChunk]) ) -> Self::SendLocalCollation { // produce a signed statement @@ -250,7 +248,6 @@ impl + Send, T> TableRouter for Router where let validated = Validated::collated_local( receipt, collation.pov.clone(), - outgoing.clone(), ); let statement = GossipStatement::new( @@ -262,7 +259,7 @@ impl + Send, T> TableRouter for Router where ); // give to network to make available. - self.fetcher.knowledge().lock().note_candidate(hash, Some(collation.pov), Some(outgoing)); + self.fetcher.knowledge().lock().note_candidate(hash, Some(collation.pov)); self.network().gossip_message(self.attestation_topic, statement.into()); for chunk in chunks.1 { diff --git a/polkadot/network/src/legacy/tests/mod.rs b/polkadot/network/src/legacy/tests/mod.rs index 7c10da7231..9c8ff8d5dd 100644 --- a/polkadot/network/src/legacy/tests/mod.rs +++ b/polkadot/network/src/legacy/tests/mod.rs @@ -20,20 +20,14 @@ use std::collections::HashMap; use super::{PolkadotProtocol, Status, Message, FullStatus}; use crate::legacy::validation::LeafWorkParams; -use polkadot_validation::GenericStatement; use polkadot_primitives::{Block, Hash}; -use polkadot_primitives::parachain::{ - CandidateReceipt, HeadData, PoVBlock, BlockData, CollatorId, ValidatorId, - StructuredUnroutedIngress, -}; +use polkadot_primitives::parachain::{CollatorId, ValidatorId}; use sp_core::crypto::UncheckedInto; use codec::Encode; use sc_network::{ PeerId, Context, ReputationChange, config::Roles, specialization::NetworkSpecialization, }; -use futures::executor::block_on; - mod validation; #[derive(Default)] @@ -94,13 +88,6 @@ impl crate::legacy::gossip::ChainContext for TestChainContext { } } -fn make_pov(block_data: Vec) -> PoVBlock { - PoVBlock { - block_data: BlockData(block_data), - ingress: polkadot_primitives::parachain::ConsolidatedIngress(Vec::new()), - } -} - fn make_status(status: &Status, roles: Roles) -> FullStatus { FullStatus { version: 1, @@ -121,11 +108,6 @@ fn make_validation_leaf_work(parent_hash: Hash, local_key: ValidatorId) -> LeafW } } -fn on_message(protocol: &mut PolkadotProtocol, ctx: &mut TestContext, from: PeerId, message: Message) { - let encoded = message.encode(); - protocol.on_message(ctx, from, encoded); -} - #[test] fn sends_session_key() { let mut protocol = PolkadotProtocol::new(None); @@ -158,93 +140,6 @@ fn sends_session_key() { } } -#[test] -fn fetches_from_those_with_knowledge() { - let mut protocol = PolkadotProtocol::new(None); - - let peer_a = PeerId::random(); - let peer_b = PeerId::random(); - let parent_hash = [0; 32].into(); - let local_key: ValidatorId = [1; 32].unchecked_into(); - - let block_data = BlockData(vec![1, 2, 3, 4]); - let block_data_hash = block_data.hash(); - let candidate_receipt = CandidateReceipt { - parachain_index: 5.into(), - collator: [255; 32].unchecked_into(), - head_data: HeadData(vec![9, 9, 9]), - parent_head: HeadData(vec![]), - signature: Default::default(), - egress_queue_roots: Vec::new(), - fees: 1_000_000, - block_data_hash, - upward_messages: Vec::new(), - erasure_root: [1u8; 32].into(), - }; - - let candidate_hash = candidate_receipt.hash(); - let a_key: ValidatorId = [3; 32].unchecked_into(); - let b_key: ValidatorId = [4; 32].unchecked_into(); - - let status = Status { collating_for: None }; - - let params = make_validation_leaf_work(parent_hash, local_key.clone()); - let session = protocol.new_validation_leaf_work(&mut TestContext::default(), params); - let knowledge = session.knowledge(); - - knowledge.lock().note_statement(a_key.clone(), &GenericStatement::Valid(candidate_hash)); - let canon_roots = StructuredUnroutedIngress(Vec::new()); - let recv = protocol.fetch_pov_block( - &mut TestContext::default(), - &candidate_receipt, - parent_hash, - canon_roots, - ); - - // connect peer A - { - let mut ctx = TestContext::default(); - protocol.on_connect(&mut ctx, peer_a.clone(), make_status(&status, Roles::AUTHORITY)); - assert!(ctx.has_message(peer_a.clone(), Message::ValidatorId(local_key))); - } - - // peer A gives session key and gets asked for data. - { - let mut ctx = TestContext::default(); - on_message(&mut protocol, &mut ctx, peer_a.clone(), Message::ValidatorId(a_key.clone())); - assert!(protocol.validators.contains_key(&a_key)); - assert!(ctx.has_message(peer_a.clone(), Message::RequestPovBlock(1, parent_hash, candidate_hash))); - } - - knowledge.lock().note_statement(b_key.clone(), &GenericStatement::Valid(candidate_hash)); - - // peer B connects and sends session key. request already assigned to A - { - let mut ctx = TestContext::default(); - protocol.on_connect(&mut ctx, peer_b.clone(), make_status(&status, Roles::AUTHORITY)); - on_message(&mut protocol, &mut ctx, peer_b.clone(), Message::ValidatorId(b_key.clone())); - assert!(!ctx.has_message(peer_b.clone(), Message::RequestPovBlock(2, parent_hash, candidate_hash))); - - } - - // peer A disconnects, triggering reassignment - { - let mut ctx = TestContext::default(); - protocol.on_disconnect(&mut ctx, peer_a.clone()); - assert!(!protocol.validators.contains_key(&a_key)); - assert!(ctx.has_message(peer_b.clone(), Message::RequestPovBlock(2, parent_hash, candidate_hash))); - } - - // peer B comes back with block data. - { - let mut ctx = TestContext::default(); - let pov_block = make_pov(block_data.0); - on_message(&mut protocol, &mut ctx, peer_b, Message::PovBlock(2, Some(pov_block.clone()))); - drop(protocol); - assert_eq!(block_on(recv).unwrap(), pov_block); - } -} - #[test] fn remove_bad_collator() { let mut protocol = PolkadotProtocol::new(None); diff --git a/polkadot/network/src/legacy/tests/validation.rs b/polkadot/network/src/legacy/tests/validation.rs index 0cfc86f22e..24473d8661 100644 --- a/polkadot/network/src/legacy/tests/validation.rs +++ b/polkadot/network/src/legacy/tests/validation.rs @@ -28,8 +28,7 @@ use crate::legacy::{PolkadotProtocol, NetworkService, GossipService, GossipMessa use polkadot_validation::{SharedTable, Network}; use polkadot_primitives::{Block, BlockNumber, Hash, Header, BlockId}; use polkadot_primitives::parachain::{ - Id as ParaId, Chain, DutyRoster, ParachainHost, TargetedMessage, - ValidatorId, StructuredUnroutedIngress, BlockIngressRoots, Status, + Id as ParaId, Chain, DutyRoster, ParachainHost, TargetedMessage, ValidatorId, Status, FeeSchedule, HeadData, Retriable, CollatorId, ErasureChunk, CandidateReceipt, }; use parking_lot::Mutex; @@ -150,7 +149,6 @@ struct ApiData { validators: Vec, duties: Vec, active_parachains: Vec<(ParaId, Option<(CollatorId, Retriable)>)>, - ingress: HashMap, } #[derive(Default, Clone)] @@ -299,17 +297,6 @@ impl ParachainHost for RuntimeApi { Ok(NativeOrEncoded::Native(Some(Vec::new()))) } - fn ParachainHost_ingress_runtime_api_impl( - &self, - _at: &BlockId, - _: ExecutionContext, - id: Option<(ParaId, Option)>, - _: Vec, - ) -> ClientResult>> { - let (id, _) = id.unwrap(); - Ok(NativeOrEncoded::Native(self.data.lock().ingress.get(&id).cloned())) - } - fn ParachainHost_get_heads_runtime_api_impl( &self, _at: &BlockId, @@ -362,34 +349,6 @@ fn build_network(n: usize, spawner: SP)-> Built { } } -#[derive(Default)] -struct IngressBuilder { - egress: HashMap<(ParaId, ParaId), Vec>>, -} - -impl IngressBuilder { - fn add_messages(&mut self, source: ParaId, messages: &[TargetedMessage]) { - for message in messages { - let target = message.target; - self.egress.entry((source, target)).or_insert_with(Vec::new).push(message.data.clone()); - } - } - - fn build(self) -> HashMap { - let mut map = HashMap::new(); - for ((source, target), messages) in self.egress { - map.entry(target).or_insert_with(Vec::new) - .push((source, polkadot_validation::message_queue_root(&messages))); - } - - for roots in map.values_mut() { - roots.sort_by_key(|&(para_id, _)| para_id); - } - - map.into_iter().map(|(k, v)| (k, BlockIngressRoots(v))).collect() - } -} - #[derive(Clone)] struct DummyGossipMessages; diff --git a/polkadot/network/src/legacy/validation.rs b/polkadot/network/src/legacy/validation.rs index 3f38282f6b..c64f21428d 100644 --- a/polkadot/network/src/legacy/validation.rs +++ b/polkadot/network/src/legacy/validation.rs @@ -23,9 +23,9 @@ use sc_network::PeerId; use polkadot_validation::{ Network as ParachainNetwork, SharedTable, Collators, Statement, GenericStatement, SignedStatement, }; -use polkadot_primitives::{Block, BlockId, Hash}; +use polkadot_primitives::{Block, Hash}; use polkadot_primitives::parachain::{ - Id as ParaId, Collation, OutgoingMessages, ParachainHost, CandidateReceipt, CollatorId, + Id as ParaId, Collation, ParachainHost, CandidateReceipt, CollatorId, ValidatorId, PoVBlock, }; use sp_api::ProvideRuntimeApi; @@ -49,8 +49,6 @@ use crate::legacy::gossip::{RegisteredMessageValidator, MessageValidationData}; use super::{NetworkService, PolkadotProtocol}; -pub use polkadot_validation::Incoming; - /// Params to instantiate validation work on a block-DAG leaf. pub struct LeafWorkParams { /// The local session key. @@ -123,8 +121,6 @@ impl ValidationNetwork where let actions = network.new_local_leaf( parent_hash, MessageValidationData { authorities }, - |queue_root| spec.availability_store.as_ref() - .and_then(|store| store.queue_by_root(queue_root)) ); actions.perform(&network); @@ -264,7 +260,6 @@ struct KnowledgeEntry { knows_block_data: Vec, knows_outgoing: Vec, pov: Option, - outgoing_messages: Option, } /// Tracks knowledge of peers. @@ -308,11 +303,9 @@ impl Knowledge { &mut self, hash: Hash, pov: Option, - outgoing_messages: Option, ) { let entry = self.candidates.entry(hash).or_insert_with(Default::default); entry.pov = entry.pov.take().or(pov); - entry.outgoing_messages = entry.outgoing_messages.take().or(outgoing_messages); } } @@ -567,32 +560,15 @@ impl + Send, T> LeafWorkDataFetcher where pub fn fetch_pov_block(&self, candidate: &CandidateReceipt) -> Pin> + Send>> { - let parachain = candidate.parachain_index; let parent_hash = self.parent_hash; let network = self.network.clone(); let candidate = candidate.clone(); let (tx, rx) = oneshot::channel(); - let canon_roots = self.api.runtime_api().ingress( - &BlockId::hash(parent_hash), - parachain, - None, - ) - .map_err(|e| - format!( - "Cannot fetch ingress for parachain {:?} at {:?}: {:?}", - parachain, - parent_hash, - e, - ) - ); - async move { network.with_spec(move |spec, ctx| { - if let Ok(Some(canon_roots)) = canon_roots { - let inner_rx = spec.fetch_pov_block(ctx, &candidate, parent_hash, canon_roots); - let _ = tx.send(inner_rx); - } + let inner_rx = spec.fetch_pov_block(ctx, &candidate, parent_hash); + let _ = tx.send(inner_rx); }); let map_err = |_| io::Error::new( diff --git a/polkadot/network/src/protocol.rs b/polkadot/network/src/protocol.rs index 79114d2c78..acdee68307 100644 --- a/polkadot/network/src/protocol.rs +++ b/polkadot/network/src/protocol.rs @@ -28,11 +28,10 @@ use futures::prelude::*; use futures::task::{Spawn, SpawnExt}; use log::{debug, trace}; -use av_store::Store as AvailabilityStore; use polkadot_primitives::{ Hash, Block, parachain::{ - PoVBlock, ValidatorId, ValidatorIndex, Collation, CandidateReceipt, OutgoingMessages, + PoVBlock, ValidatorId, ValidatorIndex, Collation, CandidateReceipt, ErasureChunk, ParachainHost, Id as ParaId, CollatorId, }, }; @@ -106,7 +105,6 @@ pub struct Service { pub fn start( service: Arc, config: Config, - availability_store: AvailabilityStore, chain_context: C, api: Arc, executor: SP, @@ -129,7 +127,6 @@ pub fn start( executor.spawn(worker_loop( config, service.clone(), - availability_store, gossip_validator, worker_sender.clone(), api, @@ -563,7 +560,6 @@ impl ProtocolHandler { async fn worker_loop( config: Config, service: Arc, - availability_store: AvailabilityStore, gossip_handle: RegisteredMessageValidator, sender: mpsc::Sender, api: Arc, @@ -624,7 +620,6 @@ async fn worker_loop( let new_leaf_actions = gossip_handle.new_local_leaf( relay_parent, crate::legacy::gossip::MessageValidationData { authorities }, - |queue_root| availability_store.queue_by_root(queue_root), ); new_leaf_actions.perform(&gossip_handle); @@ -789,7 +784,6 @@ fn distribute_local_collation( let validated = Validated::collated_local( receipt, collation.pov.clone(), - OutgoingMessages { outgoing_messages: Vec::new() }, ); let statement = crate::legacy::gossip::GossipStatement::new( @@ -914,7 +908,6 @@ impl TableRouter for Router { &self, collation: Collation, receipt: CandidateReceipt, - _outgoing: OutgoingMessages, chunks: (ValidatorIndex, &[ErasureChunk]), ) -> Self::SendLocalCollation { let message = ServiceToWorkerMsg::LocalCollation( diff --git a/polkadot/parachain/src/lib.rs b/polkadot/parachain/src/lib.rs index d3f24c34bf..1cfd3b5c91 100644 --- a/polkadot/parachain/src/lib.rs +++ b/polkadot/parachain/src/lib.rs @@ -65,8 +65,6 @@ pub struct ValidationParams { pub block_data: Vec, /// Previous head-data. pub parent_head: Vec, - /// Incoming messages. - pub ingress: Vec, } /// The result of parachain validation. diff --git a/polkadot/parachain/tests/adder/mod.rs b/polkadot/parachain/tests/adder/mod.rs index ba99659f44..e4378d9714 100644 --- a/polkadot/parachain/tests/adder/mod.rs +++ b/polkadot/parachain/tests/adder/mod.rs @@ -18,7 +18,7 @@ use polkadot_parachain as parachain; -use crate::{DummyExt, parachain::{IncomingMessage, ValidationParams}}; +use crate::{DummyExt, parachain::ValidationParams}; use codec::{Decode, Encode}; /// Head data for this parachain. @@ -75,7 +75,6 @@ pub fn execute_good_on_parent() { ValidationParams { parent_head: parent_head.encode(), block_data: block_data.encode(), - ingress: Vec::new(), }, DummyExt, parachain::wasm_executor::ExecutionMode::RemoteTest, @@ -111,7 +110,6 @@ fn execute_good_chain_on_parent() { ValidationParams { parent_head: parent_head.encode(), block_data: block_data.encode(), - ingress: Vec::new(), }, DummyExt, parachain::wasm_executor::ExecutionMode::RemoteTest, @@ -147,47 +145,8 @@ fn execute_bad_on_parent() { ValidationParams { parent_head: parent_head.encode(), block_data: block_data.encode(), - ingress: Vec::new(), }, DummyExt, parachain::wasm_executor::ExecutionMode::RemoteTest, ).unwrap_err(); } - -#[test] -fn processes_messages() { - let parent_head = HeadData { - number: 0, - parent_hash: [0; 32], - post_state: hash_state(0), - }; - - let block_data = BlockData { - state: 0, - add: 512, - }; - - let bad_message_data = vec![1]; - assert!(AddMessage::decode(&mut &bad_message_data[..]).is_err()); - - let ret = parachain::wasm_executor::validate_candidate( - TEST_CODE, - ValidationParams { - parent_head: parent_head.encode(), - block_data: block_data.encode(), - ingress: vec![ - IncomingMessage { source: 1.into(), data: (AddMessage { amount: 256 }).encode() }, - IncomingMessage { source: 2.into(), data: bad_message_data }, - IncomingMessage { source: 3.into(), data: (AddMessage { amount: 256 }).encode() }, - ], - }, - DummyExt, - parachain::wasm_executor::ExecutionMode::RemoteTest, - ).unwrap(); - - let new_head = HeadData::decode(&mut &ret.head_data[..]).unwrap(); - - assert_eq!(new_head.number, 1); - assert_eq!(new_head.parent_hash, hash_head(&parent_head)); - assert_eq!(new_head.post_state, hash_state(1024)); -} diff --git a/polkadot/parachain/tests/wasm_executor/mod.rs b/polkadot/parachain/tests/wasm_executor/mod.rs index 8873427d15..619f36580e 100644 --- a/polkadot/parachain/tests/wasm_executor/mod.rs +++ b/polkadot/parachain/tests/wasm_executor/mod.rs @@ -30,7 +30,6 @@ fn terminates_on_timeout() { ValidationParams { parent_head: Default::default(), block_data: Vec::new(), - ingress: Vec::new(), }, DummyExt, parachain::wasm_executor::ExecutionMode::RemoteTest, @@ -53,7 +52,6 @@ fn parallel_execution() { ValidationParams { parent_head: Default::default(), block_data: Vec::new(), - ingress: Vec::new(), }, DummyExt, parachain::wasm_executor::ExecutionMode::RemoteTest, @@ -63,7 +61,6 @@ fn parallel_execution() { ValidationParams { parent_head: Default::default(), block_data: Vec::new(), - ingress: Vec::new(), }, DummyExt, parachain::wasm_executor::ExecutionMode::RemoteTest, diff --git a/polkadot/primitives/src/parachain.rs b/polkadot/primitives/src/parachain.rs index 8b1381e872..4c67ab11c0 100644 --- a/polkadot/primitives/src/parachain.rs +++ b/polkadot/primitives/src/parachain.rs @@ -20,7 +20,7 @@ use rstd::prelude::*; use rstd::cmp::Ordering; use parity_scale_codec::{Encode, Decode}; use bitvec::vec::BitVec; -use super::{Hash, Balance, BlockNumber}; +use super::{Hash, Balance}; #[cfg(feature = "std")] use serde::{Serialize, Deserialize}; @@ -164,53 +164,6 @@ pub struct DutyRoster { pub validator_duty: Vec, } -/// Outgoing message data for a parachain candidate. -/// -/// This is data produced by evaluating the candidate. It contains -/// full records of all outgoing messages to other parachains. -#[derive(PartialEq, Eq, Clone, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))] -#[cfg_attr(feature = "std", serde(rename_all = "camelCase"))] -#[cfg_attr(feature = "std", serde(deny_unknown_fields))] -pub struct OutgoingMessages { - /// The outgoing messages from the execution of the parachain. - /// - /// This must be sorted in ascending order by parachain ID. - pub outgoing_messages: Vec -} - -impl OutgoingMessages { - /// Returns an iterator of slices of all outgoing message queues. - /// - /// All messages in a given slice are guaranteed to have the same target. - pub fn message_queues(&'_ self) -> impl Iterator + '_ { - let mut outgoing = &self.outgoing_messages[..]; - - rstd::iter::from_fn(move || { - if outgoing.is_empty() { return None } - let target = outgoing[0].target; - let mut end = 1; // the index of the last matching item + 1. - loop { - match outgoing.get(end) { - None => break, - Some(x) => if x.target != target { break }, - } - end += 1; - } - - let item = &outgoing[..end]; - outgoing = &outgoing[end..]; - Some(item) - }) - } -} - -/// Messages by queue root that are stored in the availability store. -#[derive(PartialEq, Clone, Decode)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Encode, Debug))] -pub struct AvailableMessages(pub Vec<(Hash, Vec)>); - - /// Compute a trie root for a set of messages, given the raw message data. #[cfg(feature = "std")] pub fn message_queue_root>(messages: I) -> Hash @@ -219,19 +172,6 @@ pub fn message_queue_root>(messages: I) -> Hash trie::trie_types::Layout::::ordered_trie_root(messages) } -#[cfg(feature = "std")] -impl From for AvailableMessages { - fn from(outgoing: OutgoingMessages) -> Self { - let queues = outgoing.message_queues().filter_map(|queue| { - let queue_root = message_queue_root(queue); - let queue_data = queue.iter().map(|msg| msg.clone().into()).collect(); - Some((queue_root, queue_data)) - }).collect(); - - AvailableMessages(queues) - } -} - /// Candidate receipt type. #[derive(PartialEq, Eq, Clone, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug))] @@ -242,9 +182,6 @@ pub struct CollationInfo { pub collator: CollatorId, /// Signature on blake2-256 of the block data by collator. pub signature: CollatorSignature, - /// Egress queue roots. Must be sorted lexicographically (ascending) - /// by parachain ID. - pub egress_queue_roots: Vec<(Id, Hash)>, /// The head-data pub head_data: HeadData, /// blake2-256 Hash of block data. @@ -259,7 +196,6 @@ impl From for CollationInfo { parachain_index: receipt.parachain_index, collator: receipt.collator, signature: receipt.signature, - egress_queue_roots: receipt.egress_queue_roots, head_data: receipt.head_data, block_data_hash: receipt.block_data_hash, upward_messages: receipt.upward_messages, @@ -294,9 +230,6 @@ pub struct CandidateReceipt { pub head_data: HeadData, /// The parent head-data. pub parent_head: HeadData, - /// Egress queue roots. Must be sorted lexicographically (ascending) - /// by parachain ID. - pub egress_queue_roots: Vec<(Id, Hash)>, /// Fees paid from the chain to the relay chain validators pub fees: Balance, /// blake2-256 Hash of block data. @@ -337,7 +270,6 @@ impl PartialEq for CandidateReceipt { self.parachain_index == info.parachain_index && self.collator == info.collator && self.signature == info.signature && - self.egress_queue_roots == info.egress_queue_roots && self.head_data == info.head_data && self.block_data_hash == info.block_data_hash && self.upward_messages == info.upward_messages @@ -369,68 +301,8 @@ pub struct Collation { pub struct PoVBlock { /// Block data. pub block_data: BlockData, - /// Ingress for the parachain. - pub ingress: ConsolidatedIngress, } -/// Parachain ingress queue message. -#[derive(PartialEq, Eq, Clone, Decode)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Encode, Debug))] -pub struct Message(#[cfg_attr(feature = "std", serde(with="bytes"))] pub Vec); - -impl AsRef<[u8]> for Message { - fn as_ref(&self) -> &[u8] { - &self.0[..] - } -} - -impl From for Message { - fn from(targeted: TargetedMessage) -> Self { - Message(targeted.data) - } -} - -/// All ingress roots at one block. -/// -/// This is an ordered vector of other parachain's egress queue roots from a specific block. -/// empty roots are omitted. Each parachain may appear once at most. -#[derive(Default, PartialEq, Eq, Clone, Encode)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Decode))] -pub struct BlockIngressRoots(pub Vec<(Id, Hash)>); - -/// All ingress roots, grouped by block number (ascending). To properly -/// interpret this struct, the user must have knowledge of which fork of the relay -/// chain all block numbers correspond to. -#[derive(Default, PartialEq, Eq, Clone, Encode)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug, Decode))] -pub struct StructuredUnroutedIngress(pub Vec<(BlockNumber, BlockIngressRoots)>); - -#[cfg(feature = "std")] -impl StructuredUnroutedIngress { - /// Get the length of all the ingress roots across all blocks. - pub fn len(&self) -> usize { - self.0.iter().fold(0, |a, (_, roots)| a + roots.0.len()) - } - - /// Returns an iterator over all ingress roots. The block number indicates - /// the height at which that root was posted to the relay chain. The parachain ID is the - /// message sender. - pub fn iter(&self) -> impl Iterator { - self.0.iter().flat_map(|&(n, ref roots)| - roots.0.iter().map(move |&(ref from, ref root)| (n, from, root)) - ) - } -} - -/// Consolidated ingress queue data. -/// -/// This is just an ordered vector of other parachains' egress queues, -/// obtained according to the routing rules. The same parachain may appear -/// more than once. -#[derive(Default, PartialEq, Eq, Clone, Decode)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize, Encode, Debug))] -pub struct ConsolidatedIngress(pub Vec<(Id, Vec)>); - /// Parachain block data. /// /// contains everything required to validate para-block, may contain block and witness data @@ -580,12 +452,6 @@ sp_api::decl_runtime_apis! { fn parachain_status(id: Id) -> Option; /// Get the given parachain's head code blob. fn parachain_code(id: Id) -> Option>; - /// Get all the unrouted ingress roots at the given block that - /// are targeting the given parachain. - /// - /// If `since` is provided, only messages since (including those in) that block - /// will be included. - fn ingress(to: Id, since: Option) -> Option; /// Extract the heads that were set by this set of extrinsics. fn get_heads(extrinsics: Vec<::Extrinsic>) -> Option>; } diff --git a/polkadot/runtime/common/src/parachains.rs b/polkadot/runtime/common/src/parachains.rs index 00e51adeaf..9fa89eacbc 100644 --- a/polkadot/runtime/common/src/parachains.rs +++ b/polkadot/runtime/common/src/parachains.rs @@ -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 Iterator for BlockNum } } -// creates a range iterator between `low` and `high`. `low` must be <= `high`. -fn number_range(low: N, high: N) -> BlockNumberRange { - BlockNumberRange { low, high } -} - // wrapper trait because an associated type of `Currency` // doesn't work.` pub trait ParachainCurrency { @@ -147,12 +141,6 @@ pub enum Origin { Parachain(ParaId), } -// result of as trie_db::NodeCodec>::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>; /// The heads of the parachains registered at present. pub Heads get(parachain_head): map hasher(blake2_256) ParaId => Option>; - /// 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; - - /// 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>; - /// 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; @@ -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 = >::block_number(); >::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 Module { ) { ::insert(id, code); ::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. - >::insert(id, >::block_number().saturating_sub(One::one())); } pub fn cleanup_para( @@ -364,19 +323,6 @@ impl Module { ) { ::remove(id); ::remove(id); - - let watermark = >::take(id); - - // clear all routing entries _to_. But not those _from_. - if let Some(watermark) = watermark { - let now = >::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())) { - >::remove(&(unrouted_block, id)); - } - } } /// Dispatch some messages from a parachain. @@ -415,8 +361,8 @@ impl Module { 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 Module { /// 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(); - ::insert(id, &head.candidate.head_data.0); - - let last_watermark = >::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) { - >::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 Module { } NeedsDispatch::put(ordered_needs_dispatch); - - // apply the ingress update. - for (to, ingress_roots) in ingress_update { - >::insert((now, to), ingress_roots); - } } /// Place any new upward messages into our queue for later dispatch. @@ -623,32 +540,6 @@ impl Module { (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) -> Option> { - let watermark = >::get(to)?; - let now = >::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| { - >::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 { let balance = T::ParachainCurrency::free_balance(*id); @@ -669,42 +560,6 @@ impl Module { 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::::EgressOutOfOrder, - ); - - // a parachain can't route to self - ensure!( - *egress_para_id != head.candidate.parachain_index, - Error::::SelfAddressed, - ); - - // no empty trie roots - ensure!( - *root != EMPTY_TRIE_ROOT.into(), - Error::::EmptyTrieRoot, - ); - - // can't route to a parachain which doesn't exist - ensure!( - iter.find(|x| x == egress_para_id).is_some(), - Error::::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 as trie_db::NodeCodec>::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)> @@ -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::>()), - ); - - 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::>())); - - 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::::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::::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::::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::::EmptyTrieRoot - ); - }); - } - #[test] fn empty_trie_root_const_is_blake2_hashed_null_node() { let hashed_null_node = as trie_db::NodeCodec>::hashed_null_node(); diff --git a/polkadot/runtime/common/src/registrar.rs b/polkadot/runtime/common/src/registrar.rs index 2775a49fec..3efdcaa45e 100644 --- a/polkadot/runtime/common/src/registrar.rs +++ b/polkadot/runtime/common/src/registrar.rs @@ -198,8 +198,6 @@ decl_storage! { #[cfg(feature = "std")] fn build(config: &GenesisConfig) { - use sp_runtime::traits::Zero; - let mut p = config.parachains.clone(); p.sort_unstable_by_key(|&(ref id, _, _)| *id); p.dedup_by_key(|&mut (ref id, _, _)| *id); @@ -213,7 +211,6 @@ fn build(config: &GenesisConfig) { // no ingress -- a chain cannot be routed to until it is live. ::insert(&id, &code); ::insert(&id, &genesis); - >::insert(&id, T::BlockNumber::zero()); // Save initial parachains in registrar Paras::insert(id, ParaInfo { scheduling: Scheduling::Always }) } @@ -907,7 +904,6 @@ mod tests { signature: block_data_hash.using_encoded(|d| collator.sign(d)), head_data: HeadData(head_data.to_vec()), parent_head: HeadData(parent_head.to_vec()), - egress_queue_roots: vec![], fees: 0, block_data_hash, upward_messages: vec![], diff --git a/polkadot/runtime/kusama/src/lib.rs b/polkadot/runtime/kusama/src/lib.rs index f85319cca8..4be1d7dacd 100644 --- a/polkadot/runtime/kusama/src/lib.rs +++ b/polkadot/runtime/kusama/src/lib.rs @@ -770,11 +770,6 @@ sp_api::impl_runtime_apis! { fn parachain_code(id: parachain::Id) -> Option> { Parachains::parachain_code(&id) } - fn ingress(to: parachain::Id, since: Option) - -> Option - { - Parachains::ingress(to, since).map(parachain::StructuredUnroutedIngress) - } fn get_heads(extrinsics: Vec<::Extrinsic>) -> Option> { extrinsics .into_iter() diff --git a/polkadot/runtime/polkadot/src/lib.rs b/polkadot/runtime/polkadot/src/lib.rs index 95f6ee3d65..105f346fcd 100644 --- a/polkadot/runtime/polkadot/src/lib.rs +++ b/polkadot/runtime/polkadot/src/lib.rs @@ -688,11 +688,6 @@ sp_api::impl_runtime_apis! { fn parachain_code(id: parachain::Id) -> Option> { Parachains::parachain_code(&id) } - fn ingress(to: parachain::Id, since: Option) - -> Option - { - Parachains::ingress(to, since).map(parachain::StructuredUnroutedIngress) - } fn get_heads(extrinsics: Vec<::Extrinsic>) -> Option> { extrinsics .into_iter() diff --git a/polkadot/test-parachains/adder/collator/src/main.rs b/polkadot/test-parachains/adder/collator/src/main.rs index b3ffb7d01f..35e45b308d 100644 --- a/polkadot/test-parachains/adder/collator/src/main.rs +++ b/polkadot/test-parachains/adder/collator/src/main.rs @@ -24,9 +24,7 @@ use sp_core::Pair; use codec::{Encode, Decode}; use primitives::{ Hash, - parachain::{ - HeadData, BlockData, Id as ParaId, Message, OutgoingMessages, Status as ParachainStatus, - }, + parachain::{HeadData, BlockData, Id as ParaId, Status as ParachainStatus}, }; use collator::{ InvalidHead, ParachainContext, Network, BuildParachainContext, load_spec, Configuration, @@ -57,13 +55,12 @@ struct AdderContext { /// The parachain context. impl ParachainContext for AdderContext { - type ProduceCandidate = Ready>; + type ProduceCandidate = Ready>; - fn produce_candidate>( + fn produce_candidate( &mut self, _relay_parent: Hash, status: ParachainStatus, - ingress: I, ) -> Self::ProduceCandidate { let adder_head = match AdderHead::decode(&mut &status.head_data.0[..]) { @@ -86,11 +83,7 @@ impl ParachainContext for AdderContext { add: adder_head.number % 100, }; - let from_messages = ::adder::process_messages( - ingress.into_iter().map(|(_, msg)| msg.0) - ); - - let next_head = ::adder::execute(adder_head.hash(), adder_head, &next_body, from_messages) + let next_head = ::adder::execute(adder_head.hash(), adder_head, &next_body) .expect("good execution params; qed"); let encoded_head = HeadData(next_head.encode()); @@ -100,7 +93,7 @@ impl ParachainContext for AdderContext { next_head.number, next_body.state.overflowing_add(next_body.add).0); db.insert(next_head.clone(), next_body); - ok((encoded_body, encoded_head, OutgoingMessages { outgoing_messages: Vec::new() })) + ok((encoded_body, encoded_head)) } } diff --git a/polkadot/test-parachains/adder/src/lib.rs b/polkadot/test-parachains/adder/src/lib.rs index 07615089c5..dfb828a1de 100644 --- a/polkadot/test-parachains/adder/src/lib.rs +++ b/polkadot/test-parachains/adder/src/lib.rs @@ -90,7 +90,6 @@ pub fn execute( parent_hash: [u8; 32], parent_head: HeadData, block_data: &BlockData, - from_messages: u64, ) -> Result { debug_assert_eq!(parent_hash, parent_head.hash()); @@ -99,7 +98,6 @@ pub fn execute( } let new_state = block_data.state.overflowing_add(block_data.add).0; - let new_state = new_state.overflowing_add(from_messages).0; Ok(HeadData { number: parent_head.number + 1, diff --git a/polkadot/test-parachains/adder/src/wasm_validation.rs b/polkadot/test-parachains/adder/src/wasm_validation.rs index 52775b009d..d887003b68 100644 --- a/polkadot/test-parachains/adder/src/wasm_validation.rs +++ b/polkadot/test-parachains/adder/src/wasm_validation.rs @@ -48,13 +48,7 @@ pub extern fn validate_block(params: *const u8, len: usize) -> u64 { let parent_hash = tiny_keccak::keccak256(¶ms.parent_head[..]); - // we also add based on incoming data from messages. ignoring unknown message - // kinds. - let from_messages = crate::process_messages( - params.ingress.iter().map(|incoming| &incoming.data[..]) - ); - - match crate::execute(parent_hash, parent_head, &block_data, from_messages) { + match crate::execute(parent_hash, parent_head, &block_data) { Ok(new_head) => parachain::write_result( &ValidationResult { head_data: new_head.encode() } ), diff --git a/polkadot/validation/src/collation.rs b/polkadot/validation/src/collation.rs index cb60d4b532..a8ea572497 100644 --- a/polkadot/validation/src/collation.rs +++ b/polkadot/validation/src/collation.rs @@ -24,8 +24,8 @@ use std::sync::Arc; use polkadot_primitives::{ BlakeTwo256, Block, Hash, HashT, BlockId, Balance, parachain::{ - CollatorId, ConsolidatedIngress, StructuredUnroutedIngress, CandidateReceipt, CollationInfo, - ParachainHost, Id as ParaId, Collation, OutgoingMessages, FeeSchedule, ErasureChunk, + CollatorId, CandidateReceipt, CollationInfo, + ParachainHost, Id as ParaId, Collation, FeeSchedule, ErasureChunk, HeadData, PoVBlock, }, }; @@ -71,7 +71,7 @@ pub async fn collation_fetch( collators: C, client: Arc

, max_block_data_size: Option, -) -> Result<(Collation, OutgoingMessages, HeadData, Balance),C::Error> +) -> Result<(Collation, HeadData, Balance),C::Error> where P::Api: ParachainHost, C: Collators + Unpin, @@ -92,8 +92,8 @@ pub async fn collation_fetch( ); match res { - Ok((messages, parent_head, fees)) => { - return Ok((collation, messages, parent_head, fees)) + Ok((parent_head, fees)) => { + return Ok((collation, parent_head, fees)) } Err(e) => { debug!("Failed to validate parachain due to API error: {}", e); @@ -199,59 +199,6 @@ pub fn egress_roots(outgoing: &mut [TargetedMessage]) -> Vec<(ParaId, Hash)> { egress_roots } -fn check_egress( - mut outgoing: Vec, - expected_egress_roots: &[(ParaId, Hash)], -) -> Result { - // stable sort messages by parachain ID. - outgoing.sort_by_key(|msg| ParaId::from(msg.target)); - - { - let mut messages_iter = outgoing.iter().peekable(); - let mut expected_egress_roots = expected_egress_roots.iter(); - while let Some(batch_target) = messages_iter.peek().map(|o| o.target) { - let expected_root = match expected_egress_roots.next() { - None => return Err(Error::MissingEgressRoot { - expected: Some(batch_target), - got: None - }), - Some(&(id, ref root)) => if id == batch_target { - root - } else { - return Err(Error::MissingEgressRoot{ - expected: Some(batch_target), - got: Some(id) - }); - } - }; - - // we borrow the iterator mutably to ensure it advances so the - // next iteration of the loop starts with `messages_iter` pointing to - // the next batch. - let messages_to = messages_iter - .clone() - .take_while(|o| o.target == batch_target) - .map(|o| { let _ = messages_iter.next(); &o.data[..] }); - - let computed_root = message_queue_root(messages_to); - if &computed_root != expected_root { - return Err(Error::EgressRootMismatch { - id: batch_target, - expected: expected_root.clone(), - got: computed_root, - }); - } - } - - // also check that there are no more additional expected roots. - if let Some((next_target, _)) = expected_egress_roots.next() { - return Err(Error::MissingEgressRoot { expected: None, got: Some(*next_target) }); - } - } - - Ok(OutgoingMessages { outgoing_messages: outgoing }) -} - struct ExternalitiesInner { parachain_index: ParaId, outgoing: Vec, @@ -309,9 +256,8 @@ impl ExternalitiesInner { fn final_checks( &mut self, upward_messages: &[UpwardMessage], - egress_queue_roots: &[(ParaId, Hash)], fees_charged: Option, - ) -> Result<(OutgoingMessages, Balance), Error> { + ) -> Result { if self.upward != upward_messages { return Err(Error::UpwardMessagesInvalid { expected: upward_messages.to_vec(), @@ -328,12 +274,8 @@ impl ExternalitiesInner { } } - let messages = check_egress( - std::mem::replace(&mut self.outgoing, Vec::new()), - &egress_queue_roots[..], - )?; - Ok((messages, self.fees_charged)) + Ok(self.fees_charged) } } @@ -376,40 +318,6 @@ pub fn validate_chunk( Ok(()) } -/// Validate incoming messages against expected roots. -pub fn validate_incoming( - roots: &StructuredUnroutedIngress, - ingress: &ConsolidatedIngress, -) -> Result<(), Error> { - if roots.len() != ingress.0.len() { - return Err(Error::IngressCanonicalityMismatch { - expected: roots.0.len(), - got: ingress.0.len() - }); - } - - let all_iter = roots.iter().zip(&ingress.0); - for ((_, expected_from, root), (got_id, messages)) in all_iter { - if expected_from != got_id { - return Err(Error::IngressChainMismatch { - expected: *expected_from, - got: *got_id - }); - } - - let got_root = message_queue_root(messages.iter().map(|msg| &msg.0[..])); - if &got_root != root { - return Err(Error::IngressRootMismatch{ - id: *expected_from, - expected: *root, - got: got_root - }); - } - } - - Ok(()) -} - // A utility function that implements most of the collation validation logic. // // Reused by `validate_collation` and `validate_receipt`. @@ -422,13 +330,12 @@ fn do_validation

( max_block_data_size: Option, fees_charged: Option, head_data: &HeadData, - queue_roots: &Vec<(ParaId, Hash)>, upward_messages: &Vec, -) -> Result<(OutgoingMessages, HeadData, Balance), Error> where +) -> Result<(HeadData, Balance), Error> where P: ProvideRuntimeApi, P::Api: ParachainHost, { - use parachain::{IncomingMessage, ValidationParams}; + use parachain::ValidationParams; if let Some(max_size) = max_block_data_size { let block_data_size = pov_block.block_data.0.len() as u64; @@ -444,22 +351,10 @@ fn do_validation

( let chain_status = api.parachain_status(relay_parent, para_id)? .ok_or_else(|| Error::InactiveParachain(para_id))?; - let roots = api.ingress(relay_parent, para_id, None)? - .ok_or_else(|| Error::InactiveParachain(para_id))?; - - validate_incoming(&roots, &pov_block.ingress)?; let params = ValidationParams { parent_head: chain_status.head_data.0.clone(), block_data: pov_block.block_data.0.clone(), - ingress: pov_block.ingress.0.iter() - .flat_map(|&(source, ref messages)| { - messages.iter().map(move |msg| IncomingMessage { - source, - data: msg.0.clone(), - }) - }) - .collect() }; let ext = Externalities::new(para_id.clone(), chain_status.balance, chain_status.fee_schedule); @@ -472,13 +367,12 @@ fn do_validation

( ) { Ok(result) => { if result.head_data == head_data.0 { - let (messages, fees) = ext.0.lock().final_checks( + let fees = ext.0.lock().final_checks( upward_messages, - queue_roots, fees_charged )?; - Ok((messages, chain_status.head_data, fees)) + Ok((chain_status.head_data, fees)) } else { Err(Error::WrongHeadData { expected: head_data.0.clone(), @@ -500,7 +394,6 @@ pub fn produce_receipt_and_chunks( n_validators: usize, parent_head: HeadData, pov: &PoVBlock, - messages: &OutgoingMessages, fees: Balance, info: &CollationInfo, ) -> Result<(CandidateReceipt, Vec), Error> @@ -508,7 +401,6 @@ pub fn produce_receipt_and_chunks( let erasure_chunks = erasure::obtain_chunks( n_validators, &pov.block_data, - Some(&messages.clone().into()) )?; let branches = erasure::branches(erasure_chunks.as_ref()); @@ -532,7 +424,6 @@ pub fn produce_receipt_and_chunks( signature: info.signature.clone(), head_data: info.head_data.clone(), parent_head, - egress_queue_roots: info.egress_queue_roots.clone(), fees, block_data_hash: info.block_data_hash.clone(), upward_messages: info.upward_messages.clone(), @@ -552,11 +443,11 @@ pub fn validate_receipt

( pov_block: &PoVBlock, receipt: &CandidateReceipt, max_block_data_size: Option, -) -> Result<(OutgoingMessages, Vec), Error> where +) -> Result, Error> where P: ProvideRuntimeApi, P::Api: ParachainHost, { - let (messages, parent_head, _fees) = do_validation( + let (parent_head, _fees) = do_validation( client, relay_parent, pov_block, @@ -564,7 +455,6 @@ pub fn validate_receipt

( max_block_data_size, Some(receipt.fees), &receipt.head_data, - &receipt.egress_queue_roots, &receipt.upward_messages, )?; @@ -583,7 +473,6 @@ pub fn validate_receipt

( n_validators, parent_head, pov_block, - &messages, receipt.fees, &receipt.clone().into(), )?; @@ -595,7 +484,7 @@ pub fn validate_receipt

( }); } - Ok((messages, chunks)) + Ok(chunks) } /// Check whether a given collation is valid. Returns `Ok` on success, error otherwise. @@ -608,7 +497,7 @@ pub fn validate_collation

( relay_parent: &BlockId, collation: &Collation, max_block_data_size: Option, -) -> Result<(OutgoingMessages, HeadData, Balance), Error> where +) -> Result<(HeadData, Balance), Error> where P: ProvideRuntimeApi, P::Api: ParachainHost, { @@ -624,7 +513,6 @@ pub fn validate_collation

( max_block_data_size, None, &collation.info.head_data, - &collation.info.egress_queue_roots, &collation.info.upward_messages, ) } @@ -636,50 +524,6 @@ mod tests { use parachain::ParachainDispatchOrigin; use polkadot_primitives::parachain::{CandidateReceipt, HeadData}; - #[test] - fn compute_and_check_egress() { - let messages = vec![ - TargetedMessage { target: 3.into(), data: vec![1, 1, 1] }, - TargetedMessage { target: 1.into(), data: vec![1, 2, 3] }, - TargetedMessage { target: 2.into(), data: vec![4, 5, 6] }, - TargetedMessage { target: 1.into(), data: vec![7, 8, 9] }, - ]; - - let root_1 = message_queue_root(&[vec![1, 2, 3], vec![7, 8, 9]]); - let root_2 = message_queue_root(&[vec![4, 5, 6]]); - let root_3 = message_queue_root(&[vec![1, 1, 1]]); - - assert!(check_egress( - messages.clone(), - &[(1.into(), root_1), (2.into(), root_2), (3.into(), root_3)], - ).is_ok()); - - let egress_roots = egress_roots(&mut messages.clone()[..]); - - assert!(check_egress( - messages.clone(), - &egress_roots[..], - ).is_ok()); - - // missing root. - assert!(check_egress( - messages.clone(), - &[(1.into(), root_1), (3.into(), root_3)], - ).is_err()); - - // extra root. - assert!(check_egress( - messages.clone(), - &[(1.into(), root_1), (2.into(), root_2), (3.into(), root_3), (4.into(), Default::default())], - ).is_err()); - - // root mismatch. - assert!(check_egress( - messages.clone(), - &[(1.into(), root_2), (2.into(), root_1), (3.into(), root_3)], - ).is_err()); - } - #[test] fn ext_rejects_local_message() { let mut ext = ExternalitiesInner { @@ -719,7 +563,6 @@ mod tests { signature: Default::default(), head_data: HeadData(Vec::new()), parent_head: HeadData(Vec::new()), - egress_queue_roots: Vec::new(), fees: 0, block_data_hash: Default::default(), upward_messages: vec![ @@ -730,7 +573,6 @@ mod tests { }; assert!(ext().final_checks( &receipt.upward_messages, - &receipt.egress_queue_roots, Some(receipt.fees), ).is_err()); let receipt = CandidateReceipt { @@ -739,7 +581,6 @@ mod tests { signature: Default::default(), head_data: HeadData(Vec::new()), parent_head: HeadData(Vec::new()), - egress_queue_roots: Vec::new(), fees: 0, block_data_hash: Default::default(), upward_messages: vec![ @@ -749,7 +590,6 @@ mod tests { }; assert!(ext().final_checks( &receipt.upward_messages, - &receipt.egress_queue_roots, Some(receipt.fees), ).is_err()); let receipt = CandidateReceipt { @@ -758,7 +598,6 @@ mod tests { signature: Default::default(), head_data: HeadData(Vec::new()), parent_head: HeadData(Vec::new()), - egress_queue_roots: Vec::new(), fees: 0, block_data_hash: Default::default(), upward_messages: vec![ @@ -768,7 +607,6 @@ mod tests { }; assert!(ext().final_checks( &receipt.upward_messages, - &receipt.egress_queue_roots, Some(receipt.fees), ).is_err()); let receipt = CandidateReceipt { @@ -777,7 +615,6 @@ mod tests { signature: Default::default(), head_data: HeadData(Vec::new()), parent_head: HeadData(Vec::new()), - egress_queue_roots: Vec::new(), fees: 0, block_data_hash: Default::default(), upward_messages: vec![ @@ -787,7 +624,6 @@ mod tests { }; assert!(ext().final_checks( &receipt.upward_messages, - &receipt.egress_queue_roots, Some(receipt.fees), ).is_ok()); } diff --git a/polkadot/validation/src/lib.rs b/polkadot/validation/src/lib.rs index 73ad3e0117..34cdaa89ee 100644 --- a/polkadot/validation/src/lib.rs +++ b/polkadot/validation/src/lib.rs @@ -38,7 +38,7 @@ use codec::Encode; use polkadot_primitives::Hash; use polkadot_primitives::parachain::{ Id as ParaId, Chain, DutyRoster, CandidateReceipt, - Statement as PrimitiveStatement, Message, OutgoingMessages, + Statement as PrimitiveStatement, Collation, PoVBlock, ErasureChunk, ValidatorSignature, ValidatorIndex, ValidatorPair, ValidatorId, }; @@ -48,7 +48,7 @@ use futures::prelude::*; pub use self::block_production::ProposerFactory; pub use self::collation::{ - validate_collation, validate_incoming, message_queue_root, egress_roots, Collators, + validate_collation, message_queue_root, egress_roots, Collators, produce_receipt_and_chunks, }; pub use self::error::Error; @@ -70,9 +70,6 @@ pub mod collation; pub mod validation_service; pub mod block_production; -/// Incoming messages; a series of sorted (ParaId, Message) pairs. -pub type Incoming = Vec<(ParaId, Vec)>; - /// A handle to a statement table router. /// /// This is expected to be a lightweight, shared type like an `Arc`. @@ -92,7 +89,6 @@ pub trait TableRouter: Clone { &self, collation: Collation, receipt: CandidateReceipt, - outgoing: OutgoingMessages, chunks: (ValidatorIndex, &[ErasureChunk]), ) -> Self::SendLocalCollation; @@ -218,18 +214,6 @@ pub fn make_group_info( } -/// Compute the (target, root, messages) of all outgoing queues. -pub fn outgoing_queues(outgoing_targeted: &'_ OutgoingMessages) - -> impl Iterator)> + '_ -{ - outgoing_targeted.message_queues().filter_map(|queue| { - let target = queue.get(0)?.target; - let queue_root = message_queue_root(queue); - let queue_data = queue.iter().map(|msg| msg.clone().into()).collect(); - Some((target, queue_root, queue_data)) - }) -} - #[cfg(test)] mod tests { use super::*; diff --git a/polkadot/validation/src/shared_table/mod.rs b/polkadot/validation/src/shared_table/mod.rs index 9a700fcbed..77ab0a78ac 100644 --- a/polkadot/validation/src/shared_table/mod.rs +++ b/polkadot/validation/src/shared_table/mod.rs @@ -24,7 +24,7 @@ use availability_store::{Store as AvailabilityStore}; use table::{self, Table, Context as TableContextTrait}; use polkadot_primitives::{Block, BlockId, Hash}; use polkadot_primitives::parachain::{ - Id as ParaId, OutgoingMessages, CandidateReceipt, ValidatorPair, ValidatorId, + Id as ParaId, CandidateReceipt, ValidatorPair, ValidatorId, AttestedCandidate, ParachainHost, PoVBlock, ValidatorIndex, ErasureChunk, }; @@ -91,7 +91,7 @@ impl TableContext { } pub(crate) enum Validation { - Valid(PoVBlock, OutgoingMessages), + Valid(PoVBlock), Invalid(PoVBlock), // should take proof. } @@ -222,10 +222,10 @@ impl Validated { /// Note that we've validated a candidate with given hash and it is good. /// outgoing message required. - pub fn known_good(hash: Hash, collation: PoVBlock, outgoing: OutgoingMessages) -> Self { + pub fn known_good(hash: Hash, collation: PoVBlock) -> Self { Validated { statement: GenericStatement::Valid(hash), - result: Validation::Valid(collation, outgoing), + result: Validation::Valid(collation), } } @@ -234,26 +234,17 @@ impl Validated { pub fn collated_local( receipt: CandidateReceipt, collation: PoVBlock, - outgoing: OutgoingMessages, ) -> Self { Validated { statement: GenericStatement::Candidate(receipt), - result: Validation::Valid(collation, outgoing), + result: Validation::Valid(collation), } } /// Get a reference to the proof-of-validation block. pub fn pov_block(&self) -> &PoVBlock { match self.result { - Validation::Valid(ref b, _) | Validation::Invalid(ref b) => b, - } - } - - /// Get a reference to the outgoing messages data, if any. - pub fn outgoing_messages(&self) -> Option<&OutgoingMessages> { - match self.result { - Validation::Valid(_, ref ex) => Some(ex), - Validation::Invalid(_) => None, + Validation::Valid(ref b) | Validation::Invalid(ref b) => b, } } } @@ -273,7 +264,7 @@ impl ParachainWork { pub fn prime>(self, api: Arc

) -> PrimedParachainWork< Fetch, - impl Send + FnMut(&BlockId, &PoVBlock, &CandidateReceipt) -> Result<(OutgoingMessages, ErasureChunk), ()> + Unpin, + impl Send + FnMut(&BlockId, &PoVBlock, &CandidateReceipt) -> Result + Unpin, > where P: Send + Sync + 'static, @@ -292,8 +283,8 @@ impl ParachainWork { ); match res { - Ok((messages, mut chunks)) => { - Ok((messages, chunks.swap_remove(local_index))) + Ok(mut chunks) => { + Ok(chunks.swap_remove(local_index)) } Err(e) => { debug!(target: "validation", "Encountered bad collation: {}", e); @@ -307,7 +298,7 @@ impl ParachainWork { /// Prime the parachain work with a custom validation function. pub fn prime_with(self, validate: F) -> PrimedParachainWork - where F: FnMut(&BlockId, &PoVBlock, &CandidateReceipt) -> Result<(OutgoingMessages, ErasureChunk), ()> + where F: FnMut(&BlockId, &PoVBlock, &CandidateReceipt) -> Result { PrimedParachainWork { inner: self, validate } } @@ -327,7 +318,7 @@ pub struct PrimedParachainWork { impl PrimedParachainWork where Fetch: Future> + Unpin, - F: FnMut(&BlockId, &PoVBlock, &CandidateReceipt) -> Result<(OutgoingMessages, ErasureChunk), ()> + Unpin, + F: FnMut(&BlockId, &PoVBlock, &CandidateReceipt) -> Result + Unpin, Err: From<::std::io::Error>, { pub async fn validate(mut self) -> Result<(Validated, Option), Err> { @@ -353,7 +344,7 @@ impl PrimedParachainWork }, None, )), - Ok((outgoing_targeted, our_chunk)) => { + Ok(our_chunk) => { self.inner.availability_store.add_erasure_chunk( self.inner.relay_parent, candidate.clone(), @@ -363,7 +354,7 @@ impl PrimedParachainWork Ok(( Validated { statement: GenericStatement::Valid(candidate_hash), - result: Validation::Valid(pov_block, outgoing_targeted), + result: Validation::Valid(pov_block), }, Some(our_chunk), )) @@ -580,9 +571,7 @@ mod tests { use super::*; use sp_keyring::Sr25519Keyring; use primitives::crypto::UncheckedInto; - use polkadot_primitives::parachain::{ - AvailableMessages, BlockData, ConsolidatedIngress, Collation, HeadData, - }; + use polkadot_primitives::parachain::{BlockData, Collation, HeadData}; use polkadot_erasure_coding::{self as erasure}; use availability_store::ProvideGossipMessages; use futures::future; @@ -592,7 +581,6 @@ mod tests { fn pov_block_with_data(data: Vec) -> PoVBlock { PoVBlock { block_data: BlockData(data), - ingress: ConsolidatedIngress(Vec::new()), } } @@ -627,7 +615,6 @@ mod tests { &self, _collation: Collation, _candidate: CandidateReceipt, - _outgoing: OutgoingMessages, _chunks: (ValidatorIndex, &[ErasureChunk]) ) -> Self::SendLocalCollation { future::ready(Ok(())) } @@ -671,7 +658,6 @@ mod tests { signature: Default::default(), head_data: HeadData(vec![1, 2, 3, 4]), parent_head: HeadData(vec![]), - egress_queue_roots: Vec::new(), fees: 1_000_000, block_data_hash: [2; 32].into(), upward_messages: Vec::new(), @@ -728,7 +714,6 @@ mod tests { signature: Default::default(), head_data: HeadData(vec![1, 2, 3, 4]), parent_head: HeadData(vec![]), - egress_queue_roots: Vec::new(), fees: 1_000_000, block_data_hash: [2; 32].into(), upward_messages: Vec::new(), @@ -766,7 +751,6 @@ mod tests { signature: Default::default(), head_data: HeadData(vec![1, 2, 3, 4]), parent_head: HeadData(vec![]), - egress_queue_roots: Vec::new(), fees: 1_000_000, block_data_hash, upward_messages: Vec::new(), @@ -792,24 +776,17 @@ mod tests { max_block_data_size: None, }; - let validated = block_on(producer.prime_with(|_, _, _| Ok(( - OutgoingMessages { outgoing_messages: Vec::new() }, - ErasureChunk { - chunk: vec![1, 2, 3], - index: local_index as u32, - proof: vec![], - }, - ))).validate()).unwrap(); + let validated = block_on(producer.prime_with(|_, _, _| Ok( + ErasureChunk { + chunk: vec![1, 2, 3], + index: local_index as u32, + proof: vec![], + } + )).validate()).unwrap(); assert_eq!(validated.0.pov_block(), &pov_block); assert_eq!(validated.0.statement, GenericStatement::Valid(hash)); - if let Some(messages) = validated.0.outgoing_messages() { - let available_messages: AvailableMessages = messages.clone().into(); - for (root, queue) in available_messages.0 { - assert_eq!(store.queue_by_root(&root), Some(queue)); - } - } assert!(store.get_erasure_chunk(&relay_parent, block_data_hash, local_index).is_some()); assert!(store.get_erasure_chunk(&relay_parent, block_data_hash, local_index + 1).is_none()); } @@ -823,7 +800,6 @@ mod tests { let block_data_hash = pov_block.block_data.hash(); let local_index = 0; let n_validators = 2; - let ex = Some(AvailableMessages(Vec::new())); let candidate = CandidateReceipt { parachain_index: para_id, @@ -831,14 +807,13 @@ mod tests { signature: Default::default(), head_data: HeadData(vec![1, 2, 3, 4]), parent_head: HeadData(vec![]), - egress_queue_roots: Vec::new(), fees: 1_000_000, block_data_hash: [2; 32].into(), upward_messages: Vec::new(), erasure_root: [1u8; 32].into(), }; - let chunks = erasure::obtain_chunks(n_validators, &pov_block.block_data, ex.as_ref()).unwrap(); + let chunks = erasure::obtain_chunks(n_validators, &pov_block.block_data).unwrap(); store.add_validator_index_and_n_validators( &relay_parent, @@ -857,23 +832,16 @@ mod tests { max_block_data_size: None, }; - let validated = block_on(producer.prime_with(|_, _, _| Ok(( - OutgoingMessages { outgoing_messages: Vec::new() }, + let validated = block_on(producer.prime_with(|_, _, _| Ok( ErasureChunk { chunk: chunks[local_index].clone(), index: local_index as u32, proof: vec![], }, - ))).validate()).unwrap(); + )).validate()).unwrap(); assert_eq!(validated.0.pov_block(), &pov_block); - if let Some(messages) = validated.0.outgoing_messages() { - let available_messages: AvailableMessages = messages.clone().into(); - for (root, queue) in available_messages.0 { - assert_eq!(store.queue_by_root(&root), Some(queue)); - } - } // This works since there are only two validators and one erasure chunk should be // enough to reconstruct the block data. assert_eq!(store.block_data(relay_parent, block_data_hash).unwrap(), pov_block.block_data); @@ -915,7 +883,6 @@ mod tests { signature: Default::default(), head_data: HeadData(vec![1, 2, 3, 4]), parent_head: HeadData(vec![]), - egress_queue_roots: Vec::new(), fees: 1_000_000, block_data_hash: [2; 32].into(), upward_messages: Vec::new(), @@ -953,7 +920,6 @@ mod tests { let para_id = ParaId::from(1); let pov_block = pov_block_with_data(vec![1, 2, 3]); - let outgoing_messages = OutgoingMessages { outgoing_messages: Vec::new() }; let parent_hash = Default::default(); let local_key = Sr25519Keyring::Alice.pair(); @@ -983,7 +949,6 @@ mod tests { signature: Default::default(), head_data: HeadData(vec![1, 2, 3, 4]), parent_head: HeadData(vec![]), - egress_queue_roots: Vec::new(), fees: 1_000_000, block_data_hash: [2; 32].into(), upward_messages: Vec::new(), @@ -994,7 +959,6 @@ mod tests { let signed_statement = shared_table.import_validated(Validated::collated_local( candidate, pov_block, - outgoing_messages, )).unwrap(); assert!(shared_table.inner.lock().validated.get(&hash).expect("validation has started").is_done()); diff --git a/polkadot/validation/src/validation_service/mod.rs b/polkadot/validation/src/validation_service/mod.rs index 51c39069d6..3c4f75f5c9 100644 --- a/polkadot/validation/src/validation_service/mod.rs +++ b/polkadot/validation/src/validation_service/mod.rs @@ -391,12 +391,11 @@ impl ParachainValidationInstances where ); collation_work.then(move |result| match result { - Ok((collation, outgoing_targeted, parent_head, fees_charged)) => { + Ok((collation, parent_head, fees_charged)) => { match crate::collation::produce_receipt_and_chunks( authorities_num, parent_head, &collation.pov, - &outgoing_targeted, fees_charged, &collation.info, ) { @@ -421,7 +420,6 @@ impl ParachainValidationInstances where router.local_collation( collation, receipt, - outgoing_targeted, (local_id, &chunks), ).map_err(|e| warn!(target: "validation", "Failed to send local collation: {:?}", e)) });