// Copyright 2017-2019 Parity Technologies (UK) Ltd. // This file is part of Substrate. // Substrate 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. // Substrate 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 Substrate. If not, see . //! Blockchain access trait use client::{self, Client as SubstrateClient, ClientInfo, BlockStatus, CallExecutor}; use client::error::Error; use client::light::fetcher::ChangesProof; use consensus::{BlockImport, Error as ConsensusError}; use sr_primitives::traits::{Block as BlockT, Header as HeaderT}; use sr_primitives::generic::{BlockId}; use sr_primitives::Justification; use primitives::{H256, Blake2Hasher, storage::StorageKey}; /// Local client abstraction for the network. pub trait Client: Send + Sync { /// Get blockchain info. fn info(&self) -> ClientInfo; /// Get block status. fn block_status(&self, id: &BlockId) -> Result; /// Get block hash by number. fn block_hash(&self, block_number: ::Number) -> Result, Error>; /// Get block header. fn header(&self, id: &BlockId) -> Result, Error>; /// Get block body. fn body(&self, id: &BlockId) -> Result>, Error>; /// Get block justification. fn justification(&self, id: &BlockId) -> Result, Error>; /// Get block header proof. fn header_proof(&self, block_number: ::Number) -> Result<(Block::Header, Vec>), Error>; /// Get storage read execution proof. fn read_proof(&self, block: &Block::Hash, key: &[u8]) -> Result>, Error>; /// Get method execution proof. fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec, Vec>), Error>; /// Get key changes proof. fn key_changes_proof( &self, first: Block::Hash, last: Block::Hash, min: Block::Hash, max: Block::Hash, key: &StorageKey ) -> Result, Error>; /// Returns `true` if the given `block` is a descendent of `base`. fn is_descendent_of(&self, base: &Block::Hash, block: &Block::Hash) -> Result; } /// Finality proof provider. pub trait FinalityProofProvider: Send + Sync { /// Prove finality of the block. fn prove_finality(&self, for_block: Block::Hash, request: &[u8]) -> Result>, Error>; } impl Client for SubstrateClient where B: client::backend::Backend + Send + Sync + 'static, E: CallExecutor + Send + Sync + 'static, Self: BlockImport, Block: BlockT, RA: Send + Sync { fn info(&self) -> ClientInfo { (self as &SubstrateClient).info() } fn block_status(&self, id: &BlockId) -> Result { (self as &SubstrateClient).block_status(id) } fn block_hash(&self, block_number: ::Number) -> Result, Error> { (self as &SubstrateClient).block_hash(block_number) } fn header(&self, id: &BlockId) -> Result, Error> { (self as &SubstrateClient).header(id) } fn body(&self, id: &BlockId) -> Result>, Error> { (self as &SubstrateClient).body(id) } fn justification(&self, id: &BlockId) -> Result, Error> { (self as &SubstrateClient).justification(id) } fn header_proof(&self, block_number: ::Number) -> Result<(Block::Header, Vec>), Error> { (self as &SubstrateClient).header_proof(&BlockId::Number(block_number)) } fn read_proof(&self, block: &Block::Hash, key: &[u8]) -> Result>, Error> { (self as &SubstrateClient).read_proof(&BlockId::Hash(block.clone()), key) } fn execution_proof(&self, block: &Block::Hash, method: &str, data: &[u8]) -> Result<(Vec, Vec>), Error> { (self as &SubstrateClient).execution_proof(&BlockId::Hash(block.clone()), method, data) } fn key_changes_proof( &self, first: Block::Hash, last: Block::Hash, min: Block::Hash, max: Block::Hash, key: &StorageKey ) -> Result, Error> { (self as &SubstrateClient).key_changes_proof(first, last, min, max, key) } fn is_descendent_of(&self, base: &Block::Hash, block: &Block::Hash) -> Result { if base == block { return Ok(false); } let tree_route = ::client::blockchain::tree_route( |id| self.header(&id)?.ok_or_else(|| client::error::Error::UnknownBlock(format!("{:?}", id)) ), BlockId::Hash(*block), BlockId::Hash(*base), )?; Ok(tree_route.common_block().hash == *base) } }