* Start to remove the `As` bound on `SimpleArtithmetic`

This just introduces standard numeric bounds, assuming a minimum of
`u32`. Also included is a saturating from/into trait allowing ergonomic
infallible conversion when you don't care if it saturates.

* Remove As from Balances trait

* Remove As from Aura module

* Remove As from Babe module

* Expunge `As` from contract

* Council module

* Democracy

* Finality tracker

* Grandpa

* First bit of indices

* indices

* Line lengths

* session

* system

* Staking

* Square up all other uses of As.

* RHD update

* Fix build/test

* Remove As trait

* line widths

* Remove final As ref

* Update srml/staking/src/lib.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Update core/client/src/cht.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Update core/client/db/src/light.rs

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* Apply suggestions from code review

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>

* whitespace

* Apply suggestions from code review

Co-Authored-By: Bastian Köcher <bkchr@users.noreply.github.com>
Co-Authored-By: André Silva <andre.beat@gmail.com>

* Bring back u32 check for number on CLI
This commit is contained in:
Gavin Wood
2019-05-22 23:11:38 +01:00
committed by GitHub
parent 36987c0205
commit 3860d7c810
60 changed files with 695 additions and 491 deletions
+7 -5
View File
@@ -44,7 +44,9 @@ use std::collections::BTreeSet;
use log::warn;
use client::error::{Error as ClientError, Result as ClientResult};
use runtime_primitives::traits::{Block as BlockT, NumberFor, As, Zero};
use runtime_primitives::traits::{
Block as BlockT, NumberFor, Zero, Bounded, SaturatedConversion, CheckedSub
};
use crate::cache::{CacheItemT, ComplexBlockId, EntryType};
use crate::cache::list_entry::{Entry, StorageEntry};
@@ -135,7 +137,7 @@ impl<Block: BlockT, T: CacheItemT, S: Storage<Block, T>> ListCache<Block, T, S>
// BUT since we're not guaranteeing to provide correct values for forks
// behind the finalized block, check if the block is finalized first
if !chain::is_finalized_block(&self.storage, at, As::sa(::std::u64::MAX))? {
if !chain::is_finalized_block(&self.storage, at, Bounded::max_value())? {
return Ok(None);
}
@@ -349,9 +351,9 @@ impl<Block: BlockT, T: CacheItemT, S: Storage<Block, T>> ListCache<Block, T, S>
) {
let mut do_pruning = || -> ClientResult<()> {
// calculate last ancient block number
let ancient_block = match block.number.as_().checked_sub(self.prune_depth.as_()) {
Some(number) => match self.storage.read_id(As::sa(number))? {
Some(hash) => ComplexBlockId::new(hash, As::sa(number)),
let ancient_block = match block.number.checked_sub(&self.prune_depth) {
Some(number) => match self.storage.read_id(number)? {
Some(hash) => ComplexBlockId::new(hash, number),
None => return Ok(()),
},
None => return Ok(()),
+3 -3
View File
@@ -25,7 +25,7 @@ use client::blockchain::Cache as BlockchainCache;
use client::error::Result as ClientResult;
use parity_codec::{Encode, Decode};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, As, Zero};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, NumberFor, Zero};
use consensus_common::well_known_cache_keys::Id as CacheKeyId;
use crate::utils::{self, COLUMN_META, db_err};
@@ -36,7 +36,7 @@ mod list_entry;
mod list_storage;
/// Minimal post-finalization age age of finalized blocks before they'll pruned.
const PRUNE_DEPTH: u64 = 1024;
const PRUNE_DEPTH: u32 = 1024;
/// The type of entry that is inserted to the cache.
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -166,7 +166,7 @@ fn get_cache_helper<'a, Block: BlockT>(
cache,
},
),
As::sa(PRUNE_DEPTH),
PRUNE_DEPTH.into(),
best_finalized_block.clone(),
)
})
+20 -17
View File
@@ -46,7 +46,10 @@ use parking_lot::{Mutex, RwLock};
use primitives::{H256, Blake2Hasher, ChangesTrieConfiguration, convert_hash};
use primitives::storage::well_known_keys;
use runtime_primitives::{generic::BlockId, Justification, StorageOverlay, ChildrenStorageOverlay};
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, As, NumberFor, Zero, Digest, DigestItem};
use runtime_primitives::traits::{
Block as BlockT, Header as HeaderT, NumberFor, Zero, One, Digest, DigestItem,
SaturatedConversion, UniqueSaturatedFrom, UniqueSaturatedInto
};
use runtime_primitives::BuildStorage;
use state_machine::backend::Backend as StateBackend;
use executor::RuntimeInfo;
@@ -446,7 +449,7 @@ impl<Block: BlockT> DbChangesTrieStorage<Block> {
min_blocks_to_keep,
&state_machine::ChangesTrieAnchorBlockId {
hash: convert_hash(&block_hash),
number: block_num.as_(),
number: block_num.saturated_into::<u64>(),
},
|node| tx.delete(columns::CHANGES_TRIE, node.as_ref()));
}
@@ -477,19 +480,19 @@ impl<Block: BlockT> state_machine::ChangesTrieRootsStorage<Blake2Hasher> for DbC
}
// we need to get hash of the block to resolve changes trie root
let block_id = if block <= self.meta.read().finalized_number.as_() {
let block_id = if block <= self.meta.read().finalized_number.saturated_into::<u64>() {
// if block is finalized, we could just read canonical hash
BlockId::Number(As::sa(block))
BlockId::Number(block.saturated_into())
} else {
// the block is not finalized
let mut current_num = anchor.number;
let mut current_hash: Block::Hash = convert_hash(&anchor.hash);
let maybe_anchor_header: Block::Header = utils::require_header::<Block>(
&*self.db, columns::KEY_LOOKUP, columns::HEADER, BlockId::Number(As::sa(current_num))
&*self.db, columns::KEY_LOOKUP, columns::HEADER, BlockId::Number(current_num.saturated_into())
).map_err(|e| e.to_string())?;
if maybe_anchor_header.hash() == current_hash {
// if anchor is canonicalized, then the block is also canonicalized
BlockId::Number(As::sa(block))
BlockId::Number(block.saturated_into())
} else {
// else (block is not finalized + anchor is not canonicalized):
// => we should find the required block hash by traversing
@@ -770,7 +773,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
)
-> Result<(), client::error::Error>
{
let number_u64 = number.as_();
let number_u64 = number.saturated_into::<u64>();
if number_u64 > self.canonicalization_delay {
let new_canonical = number_u64 - self.canonicalization_delay;
@@ -781,7 +784,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
let hash = if new_canonical == number_u64 {
hash
} else {
::client::blockchain::HeaderBackend::hash(&self.blockchain, As::sa(new_canonical))?
::client::blockchain::HeaderBackend::hash(&self.blockchain, new_canonical.saturated_into())?
.expect("existence of block with number `new_canonical` \
implies existence of blocks with all numbers before it; qed")
};
@@ -865,7 +868,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
changeset.deleted.push(key);
}
}
let number_u64 = number.as_();
let number_u64 = number.saturated_into::<u64>();
let commit = self.storage.state_db.insert_block(&hash, number_u64, &pending_block.header.parent_hash(), changeset)
.map_err(|e: state_db::Error<io::Error>| client::error::Error::from(format!("State database error: {:?}", e)))?;
apply_state_commit(&mut transaction, commit);
@@ -978,7 +981,7 @@ impl<Block: BlockT<Hash=H256>> Backend<Block> {
{
let f_num = f_header.number().clone();
if self.storage.state_db.best_canonical().map(|c| f_num.as_() > c).unwrap_or(true) {
if self.storage.state_db.best_canonical().map(|c| f_num.saturated_into::<u64>() > c).unwrap_or(true) {
let parent_hash = f_header.parent_hash().clone();
let lookup_key = utils::number_and_hash_to_lookup_key(f_num, f_hash.clone());
@@ -1126,9 +1129,9 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
let revertible = best - finalized;
let n = if revertible < n { revertible } else { n };
for c in 0 .. n.as_() {
if best == As::sa(0) {
return Ok(As::sa(c))
for c in 0 .. n.saturated_into::<u64>() {
if best.is_zero() {
return Ok(c.saturated_into::<NumberFor<Block>>())
}
let mut transaction = DBTransaction::new();
match self.storage.state_db.revert_one() {
@@ -1138,7 +1141,7 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
|| client::error::Error::UnknownBlock(
format!("Error reverting to {}. Block hash not found.", best)))?;
best -= As::sa(1); // prev block
best -= One::one(); // prev block
let hash = self.blockchain.hash(best)?.ok_or_else(
|| client::error::Error::UnknownBlock(
format!("Error reverting to {}. Block hash not found.", best)))?;
@@ -1150,7 +1153,7 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
self.blockchain.update_meta(hash, best, true, false);
self.blockchain.leaves.write().revert(removed.hash().clone(), removed.number().clone(), removed.parent_hash().clone());
}
None => return Ok(As::sa(c))
None => return Ok(c.saturated_into::<NumberFor<Block>>())
}
}
Ok(n)
@@ -1182,7 +1185,7 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
match self.blockchain.header(block) {
Ok(Some(ref hdr)) => {
let hash = hdr.hash();
if !self.storage.state_db.is_pruned(&hash, hdr.number().as_()) {
if !self.storage.state_db.is_pruned(&hash, (*hdr.number()).saturated_into::<u64>()) {
let root = H256::from_slice(hdr.state_root().as_ref());
let state = DbState::new(self.storage.clone(), root);
Ok(CachingState::new(state, self.shared_cache.clone(), Some(hash)))
@@ -1196,7 +1199,7 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
}
fn have_state_at(&self, hash: &Block::Hash, number: NumberFor<Block>) -> bool {
!self.storage.state_db.is_pruned(hash, number.as_())
!self.storage.state_db.is_pruned(hash, number.saturated_into::<u64>())
}
fn destroy_state(&self, mut state: Self::State) -> Result<(), client::error::Error> {
+8 -6
View File
@@ -17,6 +17,7 @@
//! RocksDB-based light client blockchain storage.
use std::{sync::Arc, collections::HashMap};
use std::convert::TryInto;
use parking_lot::RwLock;
use kvdb::{KeyValueDB, DBTransaction};
@@ -32,7 +33,8 @@ use parity_codec::{Decode, Encode};
use primitives::Blake2Hasher;
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT,
Zero, One, As, NumberFor, Digest, DigestItem};
Zero, One, SaturatedConversion, NumberFor, Digest, DigestItem
};
use consensus_common::well_known_cache_keys;
use crate::cache::{DbCacheSync, DbCache, ComplexBlockId, EntryType as CacheEntryType};
use crate::utils::{self, meta_keys, Meta, db_err, open_database,
@@ -271,8 +273,8 @@ impl<Block: BlockT> LightStorage<Block> {
let new_cht_start: NumberFor<Block> = cht::start_number(cht::SIZE, new_cht_number);
let new_header_cht_root = cht::compute_root::<Block::Header, Blake2Hasher, _>(
cht::SIZE, new_cht_number, (new_cht_start.as_()..)
.map(|num| self.hash(As::sa(num)))
cht::SIZE, new_cht_number, (new_cht_start.saturated_into::<u64>()..)
.map(|num| self.hash(num.saturated_into()))
)?;
transaction.put(
columns::CHT,
@@ -283,8 +285,8 @@ impl<Block: BlockT> LightStorage<Block> {
// if the header includes changes trie root, let's build a changes tries roots CHT
if header.digest().log(DigestItem::as_changes_trie_root).is_some() {
let new_changes_trie_cht_root = cht::compute_root::<Block::Header, Blake2Hasher, _>(
cht::SIZE, new_cht_number, (new_cht_start.as_()..)
.map(|num| self.changes_trie_root(BlockId::Number(As::sa(num))))
cht::SIZE, new_cht_number, (new_cht_start.saturated_into::<u64>()..)
.map(|num| self.changes_trie_root(BlockId::Number(num.saturated_into())))
)?;
transaction.put(
columns::CHT,
@@ -530,7 +532,7 @@ impl<Block> LightBlockchainStorage<Block> for LightStorage<Block>
}
/// Build the key for inserting header-CHT at given block.
fn cht_key<N: As<u64>>(cht_type: u8, block: N) -> [u8; 5] {
fn cht_key<N: TryInto<u32>>(cht_type: u8, block: N) -> [u8; 5] {
let mut key = [cht_type; 5];
key[1..].copy_from_slice(&utils::number_index_key(block));
key
+20 -16
View File
@@ -19,6 +19,7 @@
use std::sync::Arc;
use std::io;
use std::convert::TryInto;
use kvdb::{KeyValueDB, DBTransaction};
use kvdb_rocksdb::{Database, DatabaseConfig};
@@ -28,7 +29,10 @@ use client;
use parity_codec::Decode;
use trie::DBValue;
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{As, Block as BlockT, Header as HeaderT, Zero};
use runtime_primitives::traits::{
Block as BlockT, Header as HeaderT, Zero, UniqueSaturatedFrom,
UniqueSaturatedInto, SaturatedConversion, CheckedConversion
};
use crate::DatabaseSettings;
/// Number of columns in the db. Must be the same for both full && light dbs.
@@ -78,10 +82,8 @@ pub type NumberIndexKey = [u8; 4];
///
/// In the current database schema, this kind of key is only used for
/// lookups into an index, NOT for storing header data or others.
pub fn number_index_key<N>(n: N) -> NumberIndexKey where N: As<u64> {
let n: u64 = n.as_();
assert!(n & 0xffffffff00000000 == 0);
pub fn number_index_key<N: TryInto<u32>>(n: N) -> NumberIndexKey {
let n = n.checked_into::<u32>().unwrap();
[
(n >> 24) as u8,
((n >> 16) & 0xff) as u8,
@@ -93,7 +95,7 @@ pub fn number_index_key<N>(n: N) -> NumberIndexKey where N: As<u64> {
/// Convert number and hash into long lookup key for blocks that are
/// not in the canonical chain.
pub fn number_and_hash_to_lookup_key<N, H>(number: N, hash: H) -> Vec<u8> where
N: As<u64>,
N: TryInto<u32>,
H: AsRef<[u8]>
{
let mut lookup_key = number_index_key(number).to_vec();
@@ -103,18 +105,20 @@ pub fn number_and_hash_to_lookup_key<N, H>(number: N, hash: H) -> Vec<u8> where
/// Convert block lookup key into block number.
/// all block lookup keys start with the block number.
pub fn lookup_key_to_number<N>(key: &[u8]) -> client::error::Result<N> where N: As<u64> {
pub fn lookup_key_to_number<N>(key: &[u8]) -> client::error::Result<N> where
N: From<u32>
{
if key.len() < 4 {
return Err(client::error::Error::Backend("Invalid block key".into()));
}
Ok((key[0] as u64) << 24
| (key[1] as u64) << 16
| (key[2] as u64) << 8
| (key[3] as u64)).map(As::sa)
Ok((key[0] as u32) << 24
| (key[1] as u32) << 16
| (key[2] as u32) << 8
| (key[3] as u32)).map(Into::into)
}
/// Delete number to hash mapping in DB transaction.
pub fn remove_number_to_key_mapping<N: As<u64>>(
pub fn remove_number_to_key_mapping<N: TryInto<u32>>(
transaction: &mut DBTransaction,
key_lookup_col: Option<u32>,
number: N,
@@ -123,7 +127,7 @@ pub fn remove_number_to_key_mapping<N: As<u64>>(
}
/// Remove key mappings.
pub fn remove_key_mappings<N: As<u64>, H: AsRef<[u8]>>(
pub fn remove_key_mappings<N: TryInto<u32>, H: AsRef<[u8]>>(
transaction: &mut DBTransaction,
key_lookup_col: Option<u32>,
number: N,
@@ -135,7 +139,7 @@ pub fn remove_key_mappings<N: As<u64>, H: AsRef<[u8]>>(
/// Place a number mapping into the database. This maps number to current perceived
/// block hash at that position.
pub fn insert_number_to_key_mapping<N: As<u64> + Clone, H: AsRef<[u8]>>(
pub fn insert_number_to_key_mapping<N: TryInto<u32> + Clone, H: AsRef<[u8]>>(
transaction: &mut DBTransaction,
key_lookup_col: Option<u32>,
number: N,
@@ -149,7 +153,7 @@ pub fn insert_number_to_key_mapping<N: As<u64> + Clone, H: AsRef<[u8]>>(
}
/// Insert a hash to key mapping in the database.
pub fn insert_hash_to_key_mapping<N: As<u64>, H: AsRef<[u8]> + Clone>(
pub fn insert_hash_to_key_mapping<N: TryInto<u32>, H: AsRef<[u8]> + Clone>(
transaction: &mut DBTransaction,
key_lookup_col: Option<u32>,
number: N,
@@ -171,7 +175,7 @@ pub fn block_id_to_lookup_key<Block>(
id: BlockId<Block>
) -> Result<Option<Vec<u8>>, client::error::Error> where
Block: BlockT,
::runtime_primitives::traits::NumberFor<Block>: As<u64>,
::runtime_primitives::traits::NumberFor<Block>: UniqueSaturatedFrom<u64> + UniqueSaturatedInto<u64>,
{
let res = match id {
BlockId::Number(n) => db.get(
+23 -11
View File
@@ -29,7 +29,12 @@ use hash_db;
use trie;
use primitives::{H256, convert_hash};
use runtime_primitives::traits::{As, Header as HeaderT, SimpleArithmetic, One};
// We're using saturatedconversion in order to go back and forth to `u64`. this is stupid.
// instead we should just make the CHT generic over the block number.
use runtime_primitives::traits::{
Header as HeaderT, SimpleArithmetic, One, SaturatedConversion,
UniqueSaturatedInto
};
use state_machine::backend::InMemory as InMemoryState;
use state_machine::{MemoryDB, TrieBackend, Backend as StateBackend,
prove_read_on_trie_backend, read_proof_check, read_proof_check_on_proving_backend};
@@ -183,7 +188,7 @@ pub fn for_each_cht_group<Header, I, F, P>(
let mut current_cht_num = None;
let mut current_cht_blocks = Vec::new();
for block in blocks {
let new_cht_num = match block_to_cht_number(cht_size, block.as_()) {
let new_cht_num = match block_to_cht_number(cht_size, block.saturated_into()) {
Some(new_cht_num) => new_cht_num,
None => return Err(ClientError::Backend(format!(
"Cannot compute CHT root for the block #{}", block)).into()
@@ -198,7 +203,7 @@ pub fn for_each_cht_group<Header, I, F, P>(
functor_param = functor(
functor_param,
As::sa(current_cht_num),
current_cht_num.saturated_into(),
::std::mem::replace(&mut current_cht_blocks, Vec::new()),
)?;
}
@@ -210,7 +215,7 @@ pub fn for_each_cht_group<Header, I, F, P>(
if let Some(current_cht_num) = current_cht_num {
functor(
functor_param,
As::sa(current_cht_num),
current_cht_num.saturated_into(),
::std::mem::replace(&mut current_cht_blocks, Vec::new()),
)?;
}
@@ -233,7 +238,10 @@ fn build_pairs<Header, I>(
let mut hash_number = start_num;
for hash in hashes.into_iter().take(cht_size as usize) {
let hash = hash?.ok_or_else(|| ClientError::from(
ClientError::MissingHashRequiredForCHT(cht_num.as_(), hash_number.as_())
ClientError::MissingHashRequiredForCHT(
cht_num.saturated_into::<u64>(),
hash_number.saturated_into::<u64>()
)
))?;
pairs.push((
encode_cht_key(hash_number).to_vec(),
@@ -245,7 +253,10 @@ fn build_pairs<Header, I>(
if pairs.len() as u64 == cht_size {
Ok(pairs)
} else {
Err(ClientError::MissingHashRequiredForCHT(cht_num.as_(), hash_number.as_()))
Err(ClientError::MissingHashRequiredForCHT(
cht_num.saturated_into::<u64>(),
hash_number.saturated_into::<u64>()
))
}
}
@@ -256,12 +267,12 @@ fn build_pairs<Header, I>(
/// This is because the genesis hash is assumed to be known
/// and including it would be redundant.
pub fn start_number<N: SimpleArithmetic>(cht_size: u64, cht_num: N) -> N {
(cht_num * As::sa(cht_size)) + N::one()
(cht_num * cht_size.saturated_into()) + N::one()
}
/// Get the ending block of a given CHT.
pub fn end_number<N: SimpleArithmetic>(cht_size: u64, cht_num: N) -> N {
(cht_num + N::one()) * As::sa(cht_size)
(cht_num + N::one()) * cht_size.saturated_into()
}
/// Convert a block number to a CHT number.
@@ -270,13 +281,14 @@ pub fn block_to_cht_number<N: SimpleArithmetic>(cht_size: u64, block_num: N) ->
if block_num == N::zero() {
None
} else {
Some((block_num - N::one()) / As::sa(cht_size))
Some((block_num - N::one()) / cht_size.saturated_into())
}
}
/// Convert header number into CHT key.
pub fn encode_cht_key<N: As<u64>>(number: N) -> Vec<u8> {
let number: u64 = number.as_();
pub fn encode_cht_key<N: UniqueSaturatedInto<u64>>(number: N) -> Vec<u8> {
// why not just use Encode?
let number: u64 = number.saturated_into();
vec![
(number >> 56) as u8,
((number >> 48) & 0xff) as u8,
+63 -33
View File
@@ -35,8 +35,9 @@ use consensus::{
SelectChain, self,
};
use runtime_primitives::traits::{
Block as BlockT, Header as HeaderT, Zero, As, NumberFor, CurrentHeight,
BlockNumberToHash, ApiRef, ProvideRuntimeApi, Digest, DigestItem
Block as BlockT, Header as HeaderT, Zero, NumberFor, CurrentHeight,
BlockNumberToHash, ApiRef, ProvideRuntimeApi, Digest, DigestItem,
SaturatedConversion, One
};
use runtime_primitives::BuildStorage;
use crate::runtime_api::{
@@ -82,7 +83,11 @@ pub type ImportNotifications<Block> = mpsc::UnboundedReceiver<BlockImportNotific
/// A stream of block finality notifications.
pub type FinalityNotifications<Block> = mpsc::UnboundedReceiver<FinalityNotification<Block>>;
type StorageUpdate<B, Block> = <<<B as backend::Backend<Block, Blake2Hasher>>::BlockImportOperation as BlockImportOperation<Block, Blake2Hasher>>::State as state_machine::Backend<Blake2Hasher>>::Transaction;
type StorageUpdate<B, Block> = <
<
<B as backend::Backend<Block, Blake2Hasher>>::BlockImportOperation
as BlockImportOperation<Block, Blake2Hasher>
>::State as state_machine::Backend<Blake2Hasher>>::Transaction;
type ChangesUpdate = trie::MemoryDB<Blake2Hasher>;
/// Execution strategies settings.
@@ -146,13 +151,17 @@ pub trait BlockchainEvents<Block: BlockT> {
/// Get storage changes event stream.
///
/// Passing `None` as `filter_keys` subscribes to all storage changes.
fn storage_changes_notification_stream(&self, filter_keys: Option<&[StorageKey]>) -> error::Result<StorageEventStream<Block::Hash>>;
fn storage_changes_notification_stream(&self,
filter_keys: Option<&[StorageKey]>
) -> error::Result<StorageEventStream<Block::Hash>>;
}
/// Fetch block body by ID.
pub trait BlockBody<Block: BlockT> {
/// Get block body by ID. Returns `None` if the body is not stored.
fn block_body(&self, id: &BlockId<Block>) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>>;
fn block_body(&self,
id: &BlockId<Block>
) -> error::Result<Option<Vec<<Block as BlockT>::Extrinsic>>>;
}
/// Client info
@@ -242,11 +251,15 @@ impl<H> PrePostHeader<H> {
pub fn new_in_mem<E, Block, S, RA>(
executor: E,
genesis_storage: S,
) -> error::Result<Client<in_mem::Backend<Block, Blake2Hasher>, LocalCallExecutor<in_mem::Backend<Block, Blake2Hasher>, E>, Block, RA>>
where
E: CodeExecutor<Blake2Hasher> + RuntimeInfo,
S: BuildStorage,
Block: BlockT<Hash=H256>,
) -> error::Result<Client<
in_mem::Backend<Block, Blake2Hasher>,
LocalCallExecutor<in_mem::Backend<Block, Blake2Hasher>, E>,
Block,
RA
>> where
E: CodeExecutor<Blake2Hasher> + RuntimeInfo,
S: BuildStorage,
Block: BlockT<Hash=H256>,
{
new_with_backend(Arc::new(in_mem::Backend::new()), executor, genesis_storage)
}
@@ -286,7 +299,10 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
backend.begin_state_operation(&mut op, BlockId::Hash(Default::default()))?;
let state_root = op.reset_storage(genesis_storage, children_genesis_storage)?;
let genesis_block = genesis::construct_genesis_block::<Block>(state_root.into());
info!("Initializing Genesis block/state (state: {}, header-hash: {})", genesis_block.header().state_root(), genesis_block.header().hash());
info!("Initializing Genesis block/state (state: {}, header-hash: {})",
genesis_block.header().state_root(),
genesis_block.header().hash()
);
op.set_block_data(
genesis_block.deconstruct().0,
Some(vec![]),
@@ -380,7 +396,8 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
/// Get the code at a given block.
pub fn code_at(&self, id: &BlockId<Block>) -> error::Result<Vec<u8>> {
Ok(self.storage(id, &StorageKey(well_known_keys::CODE.to_vec()))?
.expect("None is returned if there's no value stored for the given key; ':code' key is always defined; qed").0)
.expect("None is returned if there's no value stored for the given key;\
':code' key is always defined; qed").0)
}
/// Get the RuntimeVersion at a given block.
@@ -419,7 +436,11 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
/// AND returning execution proof.
///
/// No changes are made.
pub fn execution_proof(&self, id: &BlockId<Block>, method: &str, call_data: &[u8]) -> error::Result<(Vec<u8>, Vec<Vec<u8>>)> {
pub fn execution_proof(&self,
id: &BlockId<Block>,
method: &str,
call_data: &[u8]
) -> error::Result<(Vec<u8>, Vec<Vec<u8>>)> {
let state = self.state_at(id)?;
let header = self.prepare_environment_block(id)?;
prove_execution(state, header, &self.executor, method, call_data)
@@ -431,18 +452,23 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
}
/// Get block hash by number.
pub fn block_hash(&self, block_number: <<Block as BlockT>::Header as HeaderT>::Number) -> error::Result<Option<Block::Hash>> {
pub fn block_hash(&self,
block_number: <<Block as BlockT>::Header as HeaderT>::Number
) -> error::Result<Option<Block::Hash>> {
self.backend.blockchain().hash(block_number)
}
/// Reads given header and generates CHT-based header proof for CHT of given size.
pub fn header_proof_with_cht_size(&self, id: &BlockId<Block>, cht_size: u64) -> error::Result<(Block::Header, Vec<Vec<u8>>)> {
pub fn header_proof_with_cht_size(&self,
id: &BlockId<Block>,
cht_size: u64
) -> error::Result<(Block::Header, Vec<Vec<u8>>)> {
let proof_error = || error::Error::Backend(format!("Failed to generate header proof for {:?}", id));
let header = self.backend.blockchain().expect_header(*id)?;
let block_num = *header.number();
let cht_num = cht::block_to_cht_number(cht_size, block_num).ok_or_else(proof_error)?;
let cht_start = cht::start_number(cht_size, cht_num);
let headers = (cht_start.as_()..).map(|num| self.block_hash(As::sa(num)));
let headers = (cht_start.saturated_into()..).map(|num| self.block_hash(num.saturated_into()));
let proof = cht::build_proof::<Block::Header, Blake2Hasher, _, _>(cht_size, cht_num, ::std::iter::once(block_num), headers)?;
Ok((header, proof))
}
@@ -460,14 +486,14 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
Some((config, storage)) => (config, storage),
None => return Ok(None),
};
let first = first.as_();
let last_num = self.backend.blockchain().expect_block_number_from_id(&last)?.as_();
let first = first.saturated_into::<u64>();
let last_num = self.backend.blockchain().expect_block_number_from_id(&last)?.saturated_into::<u64>();
if first > last_num {
return Err(error::Error::ChangesTrieAccessFailed("Invalid changes trie range".into()));
}
let finalized_number = self.backend.blockchain().info()?.finalized_number;
let oldest = storage.oldest_changes_trie_block(&config, finalized_number.as_());
let first = As::sa(::std::cmp::max(first, oldest));
let oldest = storage.oldest_changes_trie_block(&config, finalized_number.saturated_into::<u64>());
let first = ::std::cmp::max(first, oldest).saturated_into::<NumberFor<Block>>();
Ok(Some((first, last)))
}
@@ -480,20 +506,20 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
key: &StorageKey
) -> error::Result<Vec<(NumberFor<Block>, u32)>> {
let (config, storage) = self.require_changes_trie()?;
let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?.as_();
let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?.saturated_into::<u64>();
let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?;
key_changes::<_, Blake2Hasher>(
&config,
&*storage,
first.as_(),
first.saturated_into::<u64>(),
&ChangesTrieAnchorBlockId {
hash: convert_hash(&last_hash),
number: last_number,
},
self.backend.blockchain().info()?.best_number.as_(),
self.backend.blockchain().info()?.best_number.saturated_into::<u64>(),
&key.0)
.and_then(|r| r.map(|r| r.map(|(block, tx)| (As::sa(block), tx))).collect::<Result<_, _>>())
.and_then(|r| r.map(|r| r.map(|(block, tx)| (block.saturated_into(), tx))).collect::<Result<_, _>>())
.map_err(|err| error::Error::ChangesTrieAccessFailed(err))
}
@@ -543,7 +569,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
if block < self.min {
if let Some(ref root) = root {
self.required_roots_proofs.lock().insert(
As::sa(block),
block.saturated_into(),
root.clone()
);
}
@@ -563,7 +589,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
let recording_storage = AccessedRootsRecorder::<Block> {
storage,
min: min_number.as_(),
min: min_number.saturated_into::<u64>(),
required_roots_proofs: Mutex::new(BTreeMap::new()),
};
@@ -573,8 +599,12 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
);
// fetch key changes proof
let first_number = self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(first))?.as_();
let last_number = self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(last))?.as_();
let first_number = self.backend.blockchain()
.expect_block_number_from_id(&BlockId::Hash(first))?
.saturated_into::<u64>();
let last_number = self.backend.blockchain()
.expect_block_number_from_id(&BlockId::Hash(last))?
.saturated_into::<u64>();
let key_changes_proof = key_changes_proof::<_, Blake2Hasher>(
&config,
&recording_storage,
@@ -583,7 +613,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
hash: convert_hash(&last),
number: last_number,
},
max_number.as_(),
max_number.saturated_into::<u64>(),
&key.0
)
.map_err(|err| error::Error::from(error::Error::ChangesTrieAccessFailed(err)))?;
@@ -628,7 +658,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
blocks: Vec<NumberFor<Block>>
) -> error::Result<Vec<Vec<u8>>> {
let cht_start = cht::start_number(cht_size, cht_num);
let roots = (cht_start.as_()..).map(|num| self.header(&BlockId::Number(As::sa(num)))
let roots = (cht_start.saturated_into()..).map(|num| self.header(&BlockId::Number(num.saturated_into()))
.map(|block| block.and_then(|block| block.digest().log(DigestItem::as_changes_trie_root).cloned())));
let proof = cht::build_proof::<Block::Header, Blake2Hasher, _, _>(cht_size, cht_num, blocks, roots)?;
Ok(proof)
@@ -777,7 +807,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
};
let hash = import_headers.post().hash();
let height: u64 = import_headers.post().number().as_();
let height = (*import_headers.post().number()).saturated_into::<u64>();
*self.importing_block.write() = Some(hash);
@@ -1201,7 +1231,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
let mut ancestor = load_header(ancestor_hash)?;
let mut uncles = Vec::new();
for _generation in 0..max_generation.as_() {
for _generation in 0..max_generation.saturated_into() {
let children = self.backend.blockchain().children(ancestor_hash)?;
uncles.extend(children.into_iter().filter(|h| h != &current_hash));
current_hash = ancestor_hash;
@@ -1224,7 +1254,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
/// Prepare in-memory header that is used in execution environment.
fn prepare_environment_block(&self, parent: &BlockId<Block>) -> error::Result<Block::Header> {
Ok(<<Block as BlockT>::Header as HeaderT>::new(
self.backend.blockchain().expect_block_number_from_id(parent)? + As::sa(1),
self.backend.blockchain().expect_block_number_from_id(parent)? + One::one(),
Default::default(),
Default::default(),
self.backend.blockchain().expect_block_hash_from_id(&parent)?,
+10 -4
View File
@@ -21,8 +21,10 @@ use std::sync::Arc;
use parking_lot::RwLock;
use primitives::{ChangesTrieConfiguration, storage::well_known_keys};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{Block as BlockT, Header as HeaderT, Zero,
NumberFor, As, Digest, DigestItem};
use runtime_primitives::traits::{
Block as BlockT, Header as HeaderT, Zero,
NumberFor, SaturatedConversion, Digest, DigestItem
};
use runtime_primitives::{Justification, StorageOverlay, ChildrenStorageOverlay};
use state_machine::backend::{Backend as StateBackend, InMemory};
use state_machine::{self, InMemoryChangesTrieStorage, ChangesTrieAnchorBlockId};
@@ -619,7 +621,11 @@ where
if let Some(changes_trie_root) = changes_trie_root {
if let Some(changes_trie_update) = operation.changes_trie_update {
let changes_trie_root: H::Out = changes_trie_root.into();
self.changes_trie_storage.0.insert(header.number().as_(), changes_trie_root, changes_trie_update);
self.changes_trie_storage.0.insert(
(*header.number()).saturated_into::<u64>(),
changes_trie_root,
changes_trie_update
);
}
}
@@ -668,7 +674,7 @@ where
}
fn revert(&self, _n: NumberFor<Block>) -> error::Result<NumberFor<Block>> {
Ok(As::sa(0))
Ok(Zero::zero())
}
}
@@ -26,7 +26,7 @@ use futures::{IntoFuture, Future};
use parity_codec::{Encode, Decode};
use primitives::{H256, Blake2Hasher, convert_hash, NativeOrEncoded, OffchainExt};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{As, Block as BlockT, Header as HeaderT};
use runtime_primitives::traits::{One, Block as BlockT, Header as HeaderT};
use state_machine::{
self, Backend as StateBackend, CodeExecutor, OverlayedChanges,
ExecutionStrategy, create_proof_check_backend,
@@ -444,7 +444,7 @@ pub fn check_execution_proof<Header, E, H>(
let mut changes = OverlayedChanges::default();
let trie_backend = create_proof_check_backend(root, remote_proof)?;
let next_block = <Header as HeaderT>::new(
*request.header.number() + As::sa(1),
*request.header.number() + One::one(),
Default::default(),
Default::default(),
request.header.hash(),
+16 -10
View File
@@ -24,7 +24,10 @@ use futures::IntoFuture;
use hash_db::{HashDB, Hasher};
use parity_codec::Encode;
use primitives::{ChangesTrieConfiguration, convert_hash};
use runtime_primitives::traits::{As, Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor};
use runtime_primitives::traits::{
Block as BlockT, Header as HeaderT, Hash, HashFor, NumberFor,
UniqueSaturatedInto, UniqueSaturatedFrom, SaturatedConversion
};
use state_machine::{CodeExecutor, ChangesTrieRootsStorage, ChangesTrieAnchorBlockId,
TrieBackend, read_proof_check, key_changes_proof_check,
create_proof_check_backend_storage, read_child_proof_check};
@@ -288,14 +291,16 @@ impl<E, H, B: BlockT, S: BlockchainStorage<B>, F> LightDataChecker<E, H, B, S, F
prev_roots: remote_roots,
},
remote_proof,
request.first_block.0.as_(),
request.first_block.0.saturated_into::<u64>(),
&ChangesTrieAnchorBlockId {
hash: convert_hash(&request.last_block.1),
number: request.last_block.0.as_(),
number: request.last_block.0.saturated_into::<u64>(),
},
remote_max_block.as_(),
remote_max_block.saturated_into::<u64>(),
&request.key)
.map(|pairs| pairs.into_iter().map(|(b, x)| (As::sa(b), x)).collect())
.map(|pairs| pairs.into_iter().map(|(b, x)|
(b.saturated_into::<NumberFor<B>>(), x)
).collect())
.map_err(|err| ClientError::ChangesTrieAccessFailed(err))
}
@@ -438,7 +443,7 @@ impl<E, Block, H, S, F> FetchChecker<Block> for LightDataChecker<E, H, Block, S,
}
/// A view of BTreeMap<Number, Hash> as a changes trie roots storage.
struct RootsStorage<'a, Number: As<u64>, Hash: 'a> {
struct RootsStorage<'a, Number: UniqueSaturatedInto<u64> + UniqueSaturatedFrom<u64>, Hash: 'a> {
roots: (Number, &'a [Hash]),
prev_roots: BTreeMap<Number, Hash>,
}
@@ -446,15 +451,16 @@ struct RootsStorage<'a, Number: As<u64>, Hash: 'a> {
impl<'a, H, Number, Hash> ChangesTrieRootsStorage<H> for RootsStorage<'a, Number, Hash>
where
H: Hasher,
Number: Send + Sync + Eq + ::std::cmp::Ord + Copy + As<u64>,
Number: Send + Sync + Eq + ::std::cmp::Ord + Copy + UniqueSaturatedInto<u64>
+ UniqueSaturatedFrom<u64>,
Hash: 'a + Send + Sync + Clone + AsRef<[u8]>,
{
fn root(&self, _anchor: &ChangesTrieAnchorBlockId<H::Out>, block: u64) -> Result<Option<H::Out>, String> {
// we can't ask for roots from parallel forks here => ignore anchor
let root = if block < self.roots.0.as_() {
self.prev_roots.get(&As::sa(block)).cloned()
let root = if block < self.roots.0.saturated_into::<u64>() {
self.prev_roots.get(&Number::unique_saturated_from(block)).cloned()
} else {
block.checked_sub(self.roots.0.as_())
block.checked_sub(self.roots.0.saturated_into::<u64>())
.and_then(|index| self.roots.1.get(index as usize))
.cloned()
};