// Copyright 2019-2020 Parity Technologies (UK) Ltd. // This file is part of Parity Bridges Common. // Parity Bridges Common 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. // Parity Bridges Common 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 Parity Bridges Common. If not, see . //! Default generic implementation of headers source for basic Substrate client. use crate::chain::{BlockWithJustification, Chain}; use crate::client::Client; use crate::error::Error; use async_trait::async_trait; use headers_relay::{ sync_loop::SourceClient, sync_types::{HeaderIdOf, HeadersSyncPipeline, QueuedHeader, SourceHeader}, }; use relay_utils::relay_loop::Client as RelayClient; use sp_runtime::{traits::Header as HeaderT, Justification}; use std::marker::PhantomData; /// Substrate node as headers source. pub struct HeadersSource { client: Client, _phantom: PhantomData

, } impl HeadersSource { /// Create new headers source using given client. pub fn new(client: Client) -> Self { HeadersSource { client, _phantom: Default::default(), } } } impl Clone for HeadersSource { fn clone(&self) -> Self { HeadersSource { client: self.client.clone(), _phantom: Default::default(), } } } #[async_trait] impl RelayClient for HeadersSource { type Error = Error; async fn reconnect(&mut self) -> Result<(), Error> { self.client.reconnect().await } } #[async_trait] impl SourceClient

for HeadersSource where C: Chain, C::BlockNumber: relay_utils::BlockNumberBase, C::Header: Into, P: HeadersSyncPipeline, P::Header: SourceHeader, { async fn best_block_number(&self) -> Result { // we **CAN** continue to relay headers if source node is out of sync, because // target node may be missing headers that are already available at the source Ok(*self.client.best_header().await?.number()) } async fn header_by_hash(&self, hash: P::Hash) -> Result { self.client .header_by_hash(hash) .await .map(Into::into) .map_err(Into::into) } async fn header_by_number(&self, number: P::Number) -> Result { self.client .header_by_number(number) .await .map(Into::into) .map_err(Into::into) } async fn header_completion(&self, id: HeaderIdOf

) -> Result<(HeaderIdOf

, Option), Error> { let hash = id.1; let signed_block = self.client.get_block(Some(hash)).await?; let grandpa_justification = signed_block.justification().cloned(); Ok((id, grandpa_justification)) } async fn header_extra(&self, id: HeaderIdOf

, _header: QueuedHeader

) -> Result<(HeaderIdOf

, ()), Error> { Ok((id, ())) } }