Run cargo fmt on the whole code base (#9394)

* Run cargo fmt on the whole code base

* Second run

* Add CI check

* Fix compilation

* More unnecessary braces

* Handle weights

* Use --all

* Use correct attributes...

* Fix UI tests

* AHHHHHHHHH

* 🤦

* Docs

* Fix compilation

* 🤷

* Please stop

* 🤦 x 2

* More

* make rustfmt.toml consistent with polkadot

Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
Bastian Köcher
2021-07-21 16:32:32 +02:00
committed by GitHub
parent d451c38c1c
commit 7b56ab15b4
1010 changed files with 53339 additions and 51208 deletions
+219 -171
View File
@@ -18,36 +18,49 @@
//! State API backend for full nodes.
use std::collections::{BTreeMap, HashMap};
use std::sync::Arc;
use std::ops::Range;
use futures::{future, StreamExt as _, TryStreamExt as _};
use jsonrpc_pubsub::{manager::SubscriptionManager, typed::Subscriber, SubscriptionId};
use log::warn;
use jsonrpc_pubsub::{typed::Subscriber, SubscriptionId, manager::SubscriptionManager};
use rpc::{Result as RpcResult, futures::{stream, Future, Sink, Stream, future::result}};
use rpc::{
futures::{future::result, stream, Future, Sink, Stream},
Result as RpcResult,
};
use std::{
collections::{BTreeMap, HashMap},
ops::Range,
sync::Arc,
};
use sc_rpc_api::state::ReadProof;
use sp_blockchain::{
Result as ClientResult, Error as ClientError, HeaderMetadata, CachedHeaderMetadata,
HeaderBackend
CachedHeaderMetadata, Error as ClientError, HeaderBackend, HeaderMetadata,
Result as ClientResult,
};
use sp_core::{
Bytes, storage::{well_known_keys, StorageKey, StorageData, StorageChangeSet,
ChildInfo, ChildType, PrefixedStorageKey},
storage::{
well_known_keys, ChildInfo, ChildType, PrefixedStorageKey, StorageChangeSet, StorageData,
StorageKey,
},
Bytes,
};
use sp_runtime::{
generic::BlockId,
traits::{Block as BlockT, CheckedSub, NumberFor, SaturatedConversion},
};
use sp_version::RuntimeVersion;
use sp_runtime::{
generic::BlockId, traits::{Block as BlockT, NumberFor, SaturatedConversion, CheckedSub},
use sp_api::{CallApiAt, Metadata, ProvideRuntimeApi};
use super::{
client_err,
error::{Error, FutureResult, Result},
ChildStateBackend, StateBackend,
};
use sp_api::{Metadata, ProvideRuntimeApi, CallApiAt};
use super::{StateBackend, ChildStateBackend, error::{FutureResult, Error, Result}, client_err};
use std::marker::PhantomData;
use sc_client_api::{
Backend, BlockBackend, BlockchainEvents, CallExecutor, StorageProvider, ExecutorProvider,
ProofProvider
Backend, BlockBackend, BlockchainEvents, CallExecutor, ExecutorProvider, ProofProvider,
StorageProvider,
};
use std::marker::PhantomData;
/// Ranges to query in state_queryStorage.
struct QueryStorageRange<Block: BlockT> {
@@ -72,11 +85,13 @@ pub struct FullState<BE, Block: BlockT, Client> {
}
impl<BE, Block: BlockT, Client> FullState<BE, Block, Client>
where
BE: Backend<Block>,
Client: StorageProvider<Block, BE> + HeaderBackend<Block> + BlockBackend<Block>
+ HeaderMetadata<Block, Error = sp_blockchain::Error>,
Block: BlockT + 'static,
where
BE: Backend<Block>,
Client: StorageProvider<Block, BE>
+ HeaderBackend<Block>
+ BlockBackend<Block>
+ HeaderMetadata<Block, Error = sp_blockchain::Error>,
Block: BlockT + 'static,
{
/// Create new state API backend for full nodes.
pub fn new(
@@ -98,16 +113,23 @@ impl<BE, Block: BlockT, Client> FullState<BE, Block, Client>
fn split_query_storage_range(
&self,
from: Block::Hash,
to: Option<Block::Hash>
to: Option<Block::Hash>,
) -> Result<QueryStorageRange<Block>> {
let to = self.block_or_best(to).map_err(|e| invalid_block::<Block>(from, to, e.to_string()))?;
let to = self
.block_or_best(to)
.map_err(|e| invalid_block::<Block>(from, to, e.to_string()))?;
let invalid_block_err = |e: ClientError| invalid_block::<Block>(from, Some(to), e.to_string());
let invalid_block_err =
|e: ClientError| invalid_block::<Block>(from, Some(to), e.to_string());
let from_meta = self.client.header_metadata(from).map_err(invalid_block_err)?;
let to_meta = self.client.header_metadata(to).map_err(invalid_block_err)?;
if from_meta.number > to_meta.number {
return Err(invalid_block_range(&from_meta, &to_meta, "from number > to number".to_owned()))
return Err(invalid_block_range(
&from_meta,
&to_meta,
"from number > to number".to_owned(),
))
}
// check if we can get from `to` to `from` by going through parent_hashes.
@@ -116,28 +138,33 @@ impl<BE, Block: BlockT, Client> FullState<BE, Block, Client>
let mut hashes = vec![to_meta.hash];
let mut last = to_meta.clone();
while last.number > from_number {
let header_metadata = self.client
let header_metadata = self
.client
.header_metadata(last.parent)
.map_err(|e| invalid_block_range::<Block>(&last, &to_meta, e.to_string()))?;
hashes.push(header_metadata.hash);
last = header_metadata;
}
if last.hash != from_meta.hash {
return Err(invalid_block_range(&from_meta, &to_meta, "from and to are on different forks".to_owned()))
return Err(invalid_block_range(
&from_meta,
&to_meta,
"from and to are on different forks".to_owned(),
))
}
hashes.reverse();
hashes
};
// check if we can filter blocks-with-changes from some (sub)range using changes tries
let changes_trie_range = self.client
let changes_trie_range = self
.client
.max_key_changes_range(from_number, BlockId::Hash(to_meta.hash))
.map_err(client_err)?;
let filtered_range_begin = changes_trie_range
.and_then(|(begin, _)| {
// avoids a corner case where begin < from_number (happens when querying genesis)
begin.checked_sub(&from_number).map(|x| x.saturated_into::<usize>())
});
let filtered_range_begin = changes_trie_range.and_then(|(begin, _)| {
// avoids a corner case where begin < from_number (happens when querying genesis)
begin.checked_sub(&from_number).map(|x| x.saturated_into::<usize>())
});
let (unfiltered_range, filtered_range) = split_range(hashes.len(), filtered_range_begin);
Ok(QueryStorageRange {
@@ -158,7 +185,8 @@ impl<BE, Block: BlockT, Client> FullState<BE, Block, Client>
) -> Result<()> {
for block in range.unfiltered_range.start..range.unfiltered_range.end {
let block_hash = range.hashes[block].clone();
let mut block_changes = StorageChangeSet { block: block_hash.clone(), changes: Vec::new() };
let mut block_changes =
StorageChangeSet { block: block_hash.clone(), changes: Vec::new() };
let id = BlockId::hash(block_hash);
for key in keys {
let (has_changed, data) = {
@@ -191,30 +219,34 @@ impl<BE, Block: BlockT, Client> FullState<BE, Block, Client>
let (begin, end) = match range.filtered_range {
Some(ref filtered_range) => (
range.first_number + filtered_range.start.saturated_into(),
BlockId::Hash(range.hashes[filtered_range.end - 1].clone())
BlockId::Hash(range.hashes[filtered_range.end - 1].clone()),
),
None => return Ok(()),
};
let mut changes_map: BTreeMap<NumberFor<Block>, StorageChangeSet<Block::Hash>> = BTreeMap::new();
let mut changes_map: BTreeMap<NumberFor<Block>, StorageChangeSet<Block::Hash>> =
BTreeMap::new();
for key in keys {
let mut last_block = None;
let mut last_value = last_values.get(key).cloned().unwrap_or_default();
let key_changes = self.client.key_changes(begin, end, None, key).map_err(client_err)?;
for (block, _) in key_changes.into_iter().rev() {
if last_block == Some(block) {
continue;
continue
}
let block_hash = range.hashes[(block - range.first_number).saturated_into::<usize>()].clone();
let block_hash =
range.hashes[(block - range.first_number).saturated_into::<usize>()].clone();
let id = BlockId::Hash(block_hash);
let value_at_block = self.client.storage(&id, key).map_err(client_err)?;
if last_value == value_at_block {
continue;
continue
}
changes_map.entry(block)
changes_map
.entry(block)
.or_insert_with(|| StorageChangeSet { block: block_hash, changes: Vec::new() })
.changes.push((key.clone(), value_at_block.clone()));
.changes
.push((key.clone(), value_at_block.clone()));
last_block = Some(block);
last_value = value_at_block;
}
@@ -227,15 +259,22 @@ impl<BE, Block: BlockT, Client> FullState<BE, Block, Client>
}
}
impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Client> where
impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Client>
where
Block: BlockT + 'static,
BE: Backend<Block> + 'static,
Client: ExecutorProvider<Block> + StorageProvider<Block, BE>
+ ProofProvider<Block> + HeaderBackend<Block>
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + BlockchainEvents<Block>
+ CallApiAt<Block> + ProvideRuntimeApi<Block>
Client: ExecutorProvider<Block>
+ StorageProvider<Block, BE>
+ ProofProvider<Block>
+ HeaderBackend<Block>
+ HeaderMetadata<Block, Error = sp_blockchain::Error>
+ BlockchainEvents<Block>
+ CallApiAt<Block>
+ ProvideRuntimeApi<Block>
+ BlockBackend<Block>
+ Send + Sync + 'static,
+ Send
+ Sync
+ 'static,
Client::Api: Metadata<Block>,
{
fn call(
@@ -244,19 +283,21 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
method: String,
call_data: Bytes,
) -> FutureResult<Bytes> {
let r = self.block_or_best(block)
.and_then(|block| self
.client
.executor()
.call(
&BlockId::Hash(block),
&method,
&*call_data,
self.client.execution_extensions().strategies().other,
None,
)
.map(Into::into)
).map_err(client_err);
let r = self
.block_or_best(block)
.and_then(|block| {
self.client
.executor()
.call(
&BlockId::Hash(block),
&method,
&*call_data,
self.client.execution_extensions().strategies().other,
None,
)
.map(Into::into)
})
.map_err(client_err);
Box::new(result(r))
}
@@ -268,7 +309,8 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
Box::new(result(
self.block_or_best(block)
.and_then(|block| self.client.storage_keys(&BlockId::Hash(block), &prefix))
.map_err(client_err)))
.map_err(client_err),
))
}
fn storage_pairs(
@@ -279,7 +321,8 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
Box::new(result(
self.block_or_best(block)
.and_then(|block| self.client.storage_pairs(&BlockId::Hash(block), &prefix))
.map_err(client_err)))
.map_err(client_err),
))
}
fn storage_keys_paged(
@@ -291,13 +334,16 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
) -> FutureResult<Vec<StorageKey>> {
Box::new(result(
self.block_or_best(block)
.and_then(|block|
.and_then(|block| {
self.client.storage_keys_iter(
&BlockId::Hash(block), prefix.as_ref(), start_key.as_ref()
&BlockId::Hash(block),
prefix.as_ref(),
start_key.as_ref(),
)
)
})
.map(|iter| iter.take(count as usize).collect())
.map_err(client_err)))
.map_err(client_err),
))
}
fn storage(
@@ -308,7 +354,8 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
Box::new(result(
self.block_or_best(block)
.and_then(|block| self.client.storage(&BlockId::Hash(block), &key))
.map_err(client_err)))
.map_err(client_err),
))
}
fn storage_size(
@@ -328,7 +375,8 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
}
Box::new(result(
self.client.storage_pairs(&BlockId::Hash(block), &key)
self.client
.storage_pairs(&BlockId::Hash(block), &key)
.map(|kv| {
let item_sum = kv.iter().map(|(_, v)| v.0.len() as u64).sum::<u64>();
if item_sum > 0 {
@@ -337,7 +385,7 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
None
}
})
.map_err(client_err)
.map_err(client_err),
))
}
@@ -349,29 +397,26 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
Box::new(result(
self.block_or_best(block)
.and_then(|block| self.client.storage_hash(&BlockId::Hash(block), &key))
.map_err(client_err)))
.map_err(client_err),
))
}
fn metadata(&self, block: Option<Block::Hash>) -> FutureResult<Bytes> {
Box::new(result(
self.block_or_best(block)
.map_err(client_err)
.and_then(|block|
self.client.runtime_api().metadata(&BlockId::Hash(block))
.map(Into::into)
.map_err(|e| Error::Client(Box::new(e))))
))
Box::new(result(self.block_or_best(block).map_err(client_err).and_then(|block| {
self.client
.runtime_api()
.metadata(&BlockId::Hash(block))
.map(Into::into)
.map_err(|e| Error::Client(Box::new(e)))
})))
}
fn runtime_version(&self, block: Option<Block::Hash>) -> FutureResult<RuntimeVersion> {
Box::new(result(
self.block_or_best(block)
.map_err(client_err)
.and_then(|block|
self.client.runtime_version_at(&BlockId::Hash(block))
.map_err(|e| Error::Client(Box::new(e)))
)
))
Box::new(result(self.block_or_best(block).map_err(client_err).and_then(|block| {
self.client
.runtime_version_at(&BlockId::Hash(block))
.map_err(|e| Error::Client(Box::new(e)))
})))
}
fn query_storage(
@@ -394,7 +439,7 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
fn query_storage_at(
&self,
keys: Vec<StorageKey>,
at: Option<Block::Hash>
at: Option<Block::Hash>,
) -> FutureResult<Vec<StorageChangeSet<Block::Hash>>> {
let at = at.unwrap_or_else(|| self.client.info().best_hash);
self.query_storage(at, Some(at), keys)
@@ -432,14 +477,12 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
Ok(stream) => stream,
Err(err) => {
let _ = subscriber.reject(Error::from(client_err(err)).into());
return;
}
return
},
};
self.subscriptions.add(subscriber, |sink| {
let version = self.runtime_version(None.into())
.map_err(Into::into)
.wait();
let version = self.runtime_version(None.into()).map_err(Into::into).wait();
let client = self.client.clone();
let mut previous_version = version.clone();
@@ -460,12 +503,8 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
})
.compat();
sink
.sink_map_err(|e| warn!("Error sending notifications: {:?}", e))
.send_all(
stream::iter_result(vec![Ok(version)])
.chain(stream)
)
sink.sink_map_err(|e| warn!("Error sending notifications: {:?}", e))
.send_all(stream::iter_result(vec![Ok(version)]).chain(stream))
// we ignore the resulting Stream (if the first stream is over we are unsubscribed)
.map(|_| ())
});
@@ -486,45 +525,55 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
keys: Option<Vec<StorageKey>>,
) {
let keys = Into::<Option<Vec<_>>>::into(keys);
let stream = match self.client.storage_changes_notification_stream(
keys.as_ref().map(|x| &**x),
None
) {
let stream = match self
.client
.storage_changes_notification_stream(keys.as_ref().map(|x| &**x), None)
{
Ok(stream) => stream,
Err(err) => {
let _ = subscriber.reject(client_err(err).into());
return;
return
},
};
// initial values
let initial = stream::iter_result(keys
.map(|keys| {
let initial = stream::iter_result(
keys.map(|keys| {
let block = self.client.info().best_hash;
let changes = keys
.into_iter()
.map(|key| StateBackend::storage(self, Some(block.clone()).into(), key.clone())
.map(|val| (key.clone(), val))
.wait()
.unwrap_or_else(|_| (key, None))
)
.map(|key| {
StateBackend::storage(self, Some(block.clone()).into(), key.clone())
.map(|val| (key.clone(), val))
.wait()
.unwrap_or_else(|_| (key, None))
})
.collect();
vec![Ok(Ok(StorageChangeSet { block, changes }))]
}).unwrap_or_default());
})
.unwrap_or_default(),
);
self.subscriptions.add(subscriber, |sink| {
let stream = stream
.map(|(block, changes)| Ok::<_, ()>(Ok(StorageChangeSet {
block,
changes: changes.iter()
.filter_map(|(o_sk, k, v)| if o_sk.is_none() {
Some((k.clone(),v.cloned()))
} else { None }).collect(),
})))
.map(|(block, changes)| {
Ok::<_, ()>(Ok(StorageChangeSet {
block,
changes: changes
.iter()
.filter_map(|(o_sk, k, v)| {
if o_sk.is_none() {
Some((k.clone(), v.cloned()))
} else {
None
}
})
.collect(),
}))
})
.compat();
sink
.sink_map_err(|e| warn!("Error sending notifications: {:?}", e))
sink.sink_map_err(|e| warn!("Error sending notifications: {:?}", e))
.send_all(initial.chain(stream))
// we ignore the resulting Stream (if the first stream is over we are unsubscribed)
.map(|_| ())
@@ -553,21 +602,29 @@ impl<BE, Block, Client> StateBackend<Block, Client> for FullState<BE, Block, Cli
self.rpc_max_payload,
);
Box::new(result(
block_executor.trace_block()
.map_err(|e| invalid_block::<Block>(block, None, e.to_string()))
block_executor
.trace_block()
.map_err(|e| invalid_block::<Block>(block, None, e.to_string())),
))
}
}
impl<BE, Block, Client> ChildStateBackend<Block, Client> for FullState<BE, Block, Client> where
impl<BE, Block, Client> ChildStateBackend<Block, Client> for FullState<BE, Block, Client>
where
Block: BlockT + 'static,
BE: Backend<Block> + 'static,
Client: ExecutorProvider<Block> + StorageProvider<Block, BE>
Client: ExecutorProvider<Block>
+ StorageProvider<Block, BE>
+ ProofProvider<Block>
+ HeaderBackend<Block> + BlockBackend<Block>
+ HeaderMetadata<Block, Error = sp_blockchain::Error> + BlockchainEvents<Block>
+ CallApiAt<Block> + ProvideRuntimeApi<Block>
+ Send + Sync + 'static,
+ HeaderBackend<Block>
+ BlockBackend<Block>
+ HeaderMetadata<Block, Error = sp_blockchain::Error>
+ BlockchainEvents<Block>
+ CallApiAt<Block>
+ ProvideRuntimeApi<Block>
+ Send
+ Sync
+ 'static,
Client::Api: Metadata<Block>,
{
fn read_child_proof(
@@ -580,7 +637,8 @@ impl<BE, Block, Client> ChildStateBackend<Block, Client> for FullState<BE, Block
self.block_or_best(block)
.and_then(|block| {
let child_info = match ChildType::from_prefixed_key(&storage_key) {
Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key),
Some((ChildType::ParentKeyId, storage_key)) =>
ChildInfo::new_default(storage_key),
None => return Err(sp_blockchain::Error::InvalidChildStorageKey),
};
self.client
@@ -606,16 +664,14 @@ impl<BE, Block, Client> ChildStateBackend<Block, Client> for FullState<BE, Block
self.block_or_best(block)
.and_then(|block| {
let child_info = match ChildType::from_prefixed_key(&storage_key) {
Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key),
Some((ChildType::ParentKeyId, storage_key)) =>
ChildInfo::new_default(storage_key),
None => return Err(sp_blockchain::Error::InvalidChildStorageKey),
};
self.client.child_storage_keys(
&BlockId::Hash(block),
&child_info,
&prefix,
)
self.client.child_storage_keys(&BlockId::Hash(block), &child_info, &prefix)
})
.map_err(client_err)))
.map_err(client_err),
))
}
fn storage_keys_paged(
@@ -630,15 +686,20 @@ impl<BE, Block, Client> ChildStateBackend<Block, Client> for FullState<BE, Block
self.block_or_best(block)
.and_then(|block| {
let child_info = match ChildType::from_prefixed_key(&storage_key) {
Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key),
Some((ChildType::ParentKeyId, storage_key)) =>
ChildInfo::new_default(storage_key),
None => return Err(sp_blockchain::Error::InvalidChildStorageKey),
};
self.client.child_storage_keys_iter(
&BlockId::Hash(block), child_info, prefix.as_ref(), start_key.as_ref(),
&BlockId::Hash(block),
child_info,
prefix.as_ref(),
start_key.as_ref(),
)
})
.map(|iter| iter.take(count as usize).collect())
.map_err(client_err)))
.map_err(client_err),
))
}
fn storage(
@@ -651,16 +712,14 @@ impl<BE, Block, Client> ChildStateBackend<Block, Client> for FullState<BE, Block
self.block_or_best(block)
.and_then(|block| {
let child_info = match ChildType::from_prefixed_key(&storage_key) {
Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key),
Some((ChildType::ParentKeyId, storage_key)) =>
ChildInfo::new_default(storage_key),
None => return Err(sp_blockchain::Error::InvalidChildStorageKey),
};
self.client.child_storage(
&BlockId::Hash(block),
&child_info,
&key,
)
self.client.child_storage(&BlockId::Hash(block), &child_info, &key)
})
.map_err(client_err)))
.map_err(client_err),
))
}
fn storage_hash(
@@ -673,23 +732,24 @@ impl<BE, Block, Client> ChildStateBackend<Block, Client> for FullState<BE, Block
self.block_or_best(block)
.and_then(|block| {
let child_info = match ChildType::from_prefixed_key(&storage_key) {
Some((ChildType::ParentKeyId, storage_key)) => ChildInfo::new_default(storage_key),
Some((ChildType::ParentKeyId, storage_key)) =>
ChildInfo::new_default(storage_key),
None => return Err(sp_blockchain::Error::InvalidChildStorageKey),
};
self.client.child_storage_hash(
&BlockId::Hash(block),
&child_info,
&key,
)
self.client.child_storage_hash(&BlockId::Hash(block), &child_info, &key)
})
.map_err(client_err)))
.map_err(client_err),
))
}
}
/// Splits passed range into two subranges where:
/// - first range has at least one element in it;
/// - second range (optionally) starts at given `middle` element.
pub(crate) fn split_range(size: usize, middle: Option<usize>) -> (Range<usize>, Option<Range<usize>>) {
pub(crate) fn split_range(
size: usize,
middle: Option<usize>,
) -> (Range<usize>, Option<Range<usize>>) {
// check if we can filter blocks-with-changes from some (sub)range using changes tries
let range2_begin = match middle {
// some of required changes tries are pruned => use available tries
@@ -714,21 +774,9 @@ fn invalid_block_range<B: BlockT>(
) -> Error {
let to_string = |h: &CachedHeaderMetadata<B>| format!("{} ({:?})", h.number, h.hash);
Error::InvalidBlockRange {
from: to_string(from),
to: to_string(to),
details,
}
Error::InvalidBlockRange { from: to_string(from), to: to_string(to), details }
}
fn invalid_block<B: BlockT>(
from: B::Hash,
to: Option<B::Hash>,
details: String,
) -> Error {
Error::InvalidBlockRange {
from: format!("{:?}", from),
to: format!("{:?}", to),
details,
}
fn invalid_block<B: BlockT>(from: B::Hash, to: Option<B::Hash>, details: String) -> Error {
Error::InvalidBlockRange { from: format!("{:?}", from), to: format!("{:?}", to), details }
}