Pin states in memory so that they are not pruned away while still referenced (#2761)

* State pinning in client

* Canonicalization queue

* Fixed prioritization queue

* possible fix of "hash mismatch"

* Check for pinned discarded states

* Release state before finalization

* Style

* Style
This commit is contained in:
Arkadiy Paronyan
2019-06-04 10:01:12 +02:00
committed by Gavin Wood
parent 6ce7c1c8c8
commit 3b26453047
13 changed files with 392 additions and 194 deletions
+9 -9
View File
@@ -38,13 +38,13 @@ use consensus::well_known_cache_keys;
const IN_MEMORY_EXPECT_PROOF: &str = "InMemory state backend has Void error type and always suceeds; qed";
/// Light client backend.
pub struct Backend<S, F, H> {
pub struct Backend<S, F, H: Hasher> {
blockchain: Arc<Blockchain<S, F>>,
genesis_state: RwLock<Option<InMemoryState<H>>>,
}
/// Light block (header and justification) import operation.
pub struct ImportOperation<Block: BlockT, S, F, H> {
pub struct ImportOperation<Block: BlockT, S, F, H: Hasher> {
header: Option<Block::Header>,
cache: HashMap<well_known_cache_keys::Id, Vec<u8>>,
leaf_state: NewBlockState,
@@ -64,14 +64,14 @@ pub struct OnDemandState<Block: BlockT, S, F> {
}
/// On-demand or in-memory genesis state.
pub enum OnDemandOrGenesisState<Block: BlockT, S, F, H> {
pub enum OnDemandOrGenesisState<Block: BlockT, S, F, H: Hasher> {
/// On-demand state - storage values are fetched from remote nodes.
OnDemand(OnDemandState<Block, S, F>),
/// Genesis state - storage values are stored in-memory.
Genesis(InMemoryState<H>),
}
impl<S, F, H> Backend<S, F, H> {
impl<S, F, H: Hasher> Backend<S, F, H> {
/// Create new light backend.
pub fn new(blockchain: Arc<Blockchain<S, F>>) -> Self {
Self {
@@ -86,7 +86,7 @@ impl<S, F, H> Backend<S, F, H> {
}
}
impl<S: AuxStore, F, H> AuxStore for Backend<S, F, H> {
impl<S: AuxStore, F, H: Hasher> AuxStore for Backend<S, F, H> {
fn insert_aux<
'a,
'b: 'a,
@@ -387,7 +387,7 @@ where
Vec::new()
}
fn try_into_trie_backend(self) -> Option<TrieBackend<Self::TrieBackendStorage, H>> {
fn as_trie_backend(&mut self) -> Option<&TrieBackend<Self::TrieBackendStorage, H>> {
None
}
}
@@ -482,10 +482,10 @@ where
}
}
fn try_into_trie_backend(self) -> Option<TrieBackend<Self::TrieBackendStorage, H>> {
fn as_trie_backend(&mut self) -> Option<&TrieBackend<Self::TrieBackendStorage, H>> {
match self {
OnDemandOrGenesisState::OnDemand(state) => state.try_into_trie_backend(),
OnDemandOrGenesisState::Genesis(state) => state.try_into_trie_backend(),
OnDemandOrGenesisState::OnDemand(ref mut state) => state.as_trie_backend(),
OnDemandOrGenesisState::Genesis(ref mut state) => state.as_trie_backend(),
}
}
}
@@ -388,7 +388,7 @@ impl<Block, B, Remote, Local> CallExecutor<Block, Blake2Hasher> for
/// Method is executed using passed header as environment' current block.
/// Proof includes both environment preparation proof and method execution proof.
pub fn prove_execution<Block, S, E>(
state: S,
mut state: S,
header: Block::Header,
executor: &E,
method: &str,
@@ -399,13 +399,13 @@ pub fn prove_execution<Block, S, E>(
S: StateBackend<Blake2Hasher>,
E: CallExecutor<Block, Blake2Hasher>,
{
let trie_state = state.try_into_trie_backend()
let trie_state = state.as_trie_backend()
.ok_or_else(|| Box::new(state_machine::ExecutionError::UnableToGenerateProof) as Box<state_machine::Error>)?;
// prepare execution environment + record preparation proof
let mut changes = Default::default();
let (_, init_proof) = executor.prove_at_trie_state(
&trie_state,
trie_state,
&mut changes,
"Core_initialize_block",
&header.encode(),