* 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
+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()
};