mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 01:41:09 +00:00
Remove As (#2602)
* 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:
+7
-5
@@ -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
@@ -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(),
|
||||
)
|
||||
})
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 != ¤t_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)?,
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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()
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user