// Copyright 2017-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 . //! Validator-side view of collation. //! //! This module contains type definitions, a trait for a batch of collators, and a trait for //! attempting to fetch a collation repeatedly until a valid one is obtained. use std::sync::Arc; use polkadot_primitives::{ BlakeTwo256, Block, Hash, HashT, parachain::{ CollatorId, ParachainHost, Id as ParaId, Collation, ErasureChunk, CollationInfo, }, }; use polkadot_erasure_coding as erasure; use sp_api::ProvideRuntimeApi; use futures::prelude::*; use log::debug; /// Encapsulates connections to collators and allows collation on any parachain. /// /// This is expected to be a lightweight, shared type like an `Arc`. pub trait Collators: Clone { /// Errors when producing collations. type Error: std::fmt::Debug; /// A full collation. type Collation: Future>; /// Collate on a specific parachain, building on a given relay chain parent hash. /// /// The returned collation should be checked for basic validity in the signature /// and will be checked for state-transition validity by the consumer of this trait. /// /// This does not have to guarantee local availability, as a valid collation /// will be passed to the `TableRouter` instance. /// /// The returned future may be prematurely concluded if the `relay_parent` goes /// out of date. fn collate(&self, parachain: ParaId, relay_parent: Hash) -> Self::Collation; /// Note a bad collator. TODO: take proof (https://github.com/paritytech/polkadot/issues/217) fn note_bad_collator(&self, collator: CollatorId); } /// A future which resolves when a collation is available. pub async fn collation_fetch( validation_pool: Option, parachain: ParaId, relay_parent: Hash, collators: C, client: Arc

, max_block_data_size: Option, n_validators: usize, ) -> Result<(CollationInfo, crate::pipeline::FullOutput), C::Error> where P::Api: ParachainHost, C: Collators + Unpin, P: ProvideRuntimeApi, ::Collation: Unpin, { loop { let collation = collators.collate(parachain, relay_parent).await?; let Collation { info, pov } = collation; let res = crate::pipeline::full_output_validation_with_api( validation_pool.as_ref(), &*client, &info, &pov, &relay_parent, max_block_data_size, n_validators, ); match res { Ok(full_output) => { return Ok((info, full_output)) } Err(e) => { debug!("Failed to validate parachain due to API error: {}", e); // just continue if we got a bad collation or failed to validate collators.note_bad_collator(info.collator) } } } } /// Validate an erasure chunk against an expected root. pub fn validate_chunk( root: &Hash, chunk: &ErasureChunk, ) -> Result<(), ()> { let expected = erasure::branch_hash(root, &chunk.proof, chunk.index as usize).map_err(|_| ())?; let got = BlakeTwo256::hash(&chunk.chunk); if expected != got { return Err(()) } Ok(()) }