mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 17:01:09 +00:00
Kill the light client, CHTs and change tries. (#10080)
* Remove light client, change tries and CHTs * Update tests * fmt * Restore changes_root * Fixed benches * Cargo fmt * fmt * fmt
This commit is contained in:
@@ -30,9 +30,8 @@ use log::info;
|
||||
use prometheus_endpoint::Registry;
|
||||
use sc_chain_spec::get_extension;
|
||||
use sc_client_api::{
|
||||
execution_extensions::ExecutionExtensions, light::RemoteBlockchain,
|
||||
proof_provider::ProofProvider, BadBlocks, BlockBackend, BlockchainEvents, ExecutorProvider,
|
||||
ForkBlocks, StorageProvider, UsageProvider,
|
||||
execution_extensions::ExecutionExtensions, proof_provider::ProofProvider, BadBlocks,
|
||||
BlockBackend, BlockchainEvents, ExecutorProvider, ForkBlocks, StorageProvider, UsageProvider,
|
||||
};
|
||||
use sc_client_db::{Backend, DatabaseSettings};
|
||||
use sc_consensus::import_queue::ImportQueue;
|
||||
@@ -40,7 +39,7 @@ use sc_executor::RuntimeVersionOf;
|
||||
use sc_keystore::LocalKeystore;
|
||||
use sc_network::{
|
||||
block_request_handler::{self, BlockRequestHandler},
|
||||
config::{OnDemand, Role, SyncMode},
|
||||
config::{Role, SyncMode},
|
||||
light_client_requests::{self, handler::LightClientRequestHandler},
|
||||
state_request_handler::{self, StateRequestHandler},
|
||||
warp_request_handler::{self, RequestHandler as WarpSyncRequestHandler, WarpSyncProvider},
|
||||
@@ -381,23 +380,19 @@ where
|
||||
pub struct SpawnTasksParams<'a, TBl: BlockT, TCl, TExPool, TRpc, Backend> {
|
||||
/// The service configuration.
|
||||
pub config: Configuration,
|
||||
/// A shared client returned by `new_full_parts`/`new_light_parts`.
|
||||
/// A shared client returned by `new_full_parts`.
|
||||
pub client: Arc<TCl>,
|
||||
/// A shared backend returned by `new_full_parts`/`new_light_parts`.
|
||||
/// A shared backend returned by `new_full_parts`.
|
||||
pub backend: Arc<Backend>,
|
||||
/// A task manager returned by `new_full_parts`/`new_light_parts`.
|
||||
/// A task manager returned by `new_full_parts`.
|
||||
pub task_manager: &'a mut TaskManager,
|
||||
/// A shared keystore returned by `new_full_parts`/`new_light_parts`.
|
||||
/// A shared keystore returned by `new_full_parts`.
|
||||
pub keystore: SyncCryptoStorePtr,
|
||||
/// An optional, shared data fetcher for light clients.
|
||||
pub on_demand: Option<Arc<OnDemand<TBl>>>,
|
||||
/// A shared transaction pool.
|
||||
pub transaction_pool: Arc<TExPool>,
|
||||
/// A RPC extension builder. Use `NoopRpcExtensionBuilder` if you just want to pass in the
|
||||
/// extensions directly.
|
||||
pub rpc_extensions_builder: Box<dyn RpcExtensionBuilder<Output = TRpc> + Send>,
|
||||
/// An optional, shared remote blockchain instance. Used for light clients.
|
||||
pub remote_blockchain: Option<Arc<dyn RemoteBlockchain<TBl>>>,
|
||||
/// A shared network instance.
|
||||
pub network: Arc<NetworkService<TBl, <TBl as BlockT>::Hash>>,
|
||||
/// A Sender for RPC requests.
|
||||
@@ -475,12 +470,10 @@ where
|
||||
mut config,
|
||||
task_manager,
|
||||
client,
|
||||
on_demand: _,
|
||||
backend,
|
||||
keystore,
|
||||
transaction_pool,
|
||||
rpc_extensions_builder,
|
||||
remote_blockchain: _,
|
||||
network,
|
||||
system_rpc_tx,
|
||||
telemetry,
|
||||
@@ -725,7 +718,7 @@ where
|
||||
pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl> {
|
||||
/// The service configuration.
|
||||
pub config: &'a Configuration,
|
||||
/// A shared client returned by `new_full_parts`/`new_light_parts`.
|
||||
/// A shared client returned by `new_full_parts`.
|
||||
pub client: Arc<TCl>,
|
||||
/// A shared transaction pool.
|
||||
pub transaction_pool: Arc<TExPool>,
|
||||
@@ -733,8 +726,6 @@ pub struct BuildNetworkParams<'a, TBl: BlockT, TExPool, TImpQu, TCl> {
|
||||
pub spawn_handle: SpawnTaskHandle,
|
||||
/// An import queue.
|
||||
pub import_queue: TImpQu,
|
||||
/// An optional, shared data fetcher for light clients.
|
||||
pub on_demand: Option<Arc<OnDemand<TBl>>>,
|
||||
/// A block announce validator builder.
|
||||
pub block_announce_validator_builder:
|
||||
Option<Box<dyn FnOnce(Arc<TCl>) -> Box<dyn BlockAnnounceValidator<TBl> + Send> + Send>>,
|
||||
@@ -773,7 +764,6 @@ where
|
||||
transaction_pool,
|
||||
spawn_handle,
|
||||
import_queue,
|
||||
on_demand,
|
||||
block_announce_validator_builder,
|
||||
warp_sync,
|
||||
} = params;
|
||||
@@ -869,7 +859,6 @@ where
|
||||
},
|
||||
network_config: config.network.clone(),
|
||||
chain: client.clone(),
|
||||
on_demand,
|
||||
transaction_pool: transaction_pool_adapter as _,
|
||||
import_queue: Box::new(import_queue),
|
||||
protocol_id,
|
||||
|
||||
@@ -26,10 +26,7 @@ use sp_core::{
|
||||
NativeOrEncoded, NeverNativeValue,
|
||||
};
|
||||
use sp_externalities::Extensions;
|
||||
use sp_runtime::{
|
||||
generic::BlockId,
|
||||
traits::{Block as BlockT, NumberFor},
|
||||
};
|
||||
use sp_runtime::{generic::BlockId, traits::Block as BlockT};
|
||||
use sp_state_machine::{
|
||||
self, backend::Backend as _, ExecutionManager, ExecutionStrategy, Ext, OverlayedChanges,
|
||||
StateMachine, StorageProof,
|
||||
@@ -153,8 +150,6 @@ where
|
||||
extensions: Option<Extensions>,
|
||||
) -> sp_blockchain::Result<Vec<u8>> {
|
||||
let mut changes = OverlayedChanges::default();
|
||||
let changes_trie =
|
||||
backend::changes_tries_state_at_block(at, self.backend.changes_trie_storage())?;
|
||||
let state = self.backend.state_at(*at)?;
|
||||
let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state);
|
||||
let runtime_code =
|
||||
@@ -168,7 +163,6 @@ where
|
||||
|
||||
let return_data = StateMachine::new(
|
||||
&state,
|
||||
changes_trie,
|
||||
&mut changes,
|
||||
&self.executor,
|
||||
method,
|
||||
@@ -208,8 +202,6 @@ where
|
||||
where
|
||||
ExecutionManager<EM>: Clone,
|
||||
{
|
||||
let changes_trie_state =
|
||||
backend::changes_tries_state_at_block(at, self.backend.changes_trie_storage())?;
|
||||
let mut storage_transaction_cache = storage_transaction_cache.map(|c| c.borrow_mut());
|
||||
|
||||
let state = self.backend.state_at(*at)?;
|
||||
@@ -243,7 +235,6 @@ where
|
||||
|
||||
let mut state_machine = StateMachine::new(
|
||||
&backend,
|
||||
changes_trie_state,
|
||||
changes,
|
||||
&self.executor,
|
||||
method,
|
||||
@@ -262,7 +253,6 @@ where
|
||||
None => {
|
||||
let mut state_machine = StateMachine::new(
|
||||
&state,
|
||||
changes_trie_state,
|
||||
changes,
|
||||
&self.executor,
|
||||
method,
|
||||
@@ -286,11 +276,9 @@ where
|
||||
|
||||
fn runtime_version(&self, id: &BlockId<Block>) -> sp_blockchain::Result<RuntimeVersion> {
|
||||
let mut overlay = OverlayedChanges::default();
|
||||
let changes_trie_state =
|
||||
backend::changes_tries_state_at_block(id, self.backend.changes_trie_storage())?;
|
||||
let state = self.backend.state_at(*id)?;
|
||||
let mut cache = StorageTransactionCache::<Block, B::State>::default();
|
||||
let mut ext = Ext::new(&mut overlay, &mut cache, &state, changes_trie_state, None);
|
||||
let mut ext = Ext::new(&mut overlay, &mut cache, &state, None);
|
||||
let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state);
|
||||
let runtime_code =
|
||||
state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
@@ -317,7 +305,7 @@ where
|
||||
state_runtime_code.runtime_code().map_err(sp_blockchain::Error::RuntimeCode)?;
|
||||
let runtime_code = self.check_override(runtime_code, at)?;
|
||||
|
||||
sp_state_machine::prove_execution_on_trie_backend::<_, _, NumberFor<Block>, _, _>(
|
||||
sp_state_machine::prove_execution_on_trie_backend(
|
||||
&trie_backend,
|
||||
&mut Default::default(),
|
||||
&self.executor,
|
||||
|
||||
@@ -23,7 +23,6 @@ use super::{
|
||||
genesis,
|
||||
};
|
||||
use codec::{Decode, Encode};
|
||||
use hash_db::Prefix;
|
||||
use log::{info, trace, warn};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use prometheus_endpoint::Registry;
|
||||
@@ -31,18 +30,15 @@ use rand::Rng;
|
||||
use sc_block_builder::{BlockBuilderApi, BlockBuilderProvider, RecordProof};
|
||||
use sc_client_api::{
|
||||
backend::{
|
||||
self, apply_aux, changes_tries_state_at_block, BlockImportOperation, ClientImportOperation,
|
||||
Finalizer, ImportSummary, LockImportRun, NewBlockState, PrunableStateChangesTrieStorage,
|
||||
StorageProvider,
|
||||
self, apply_aux, BlockImportOperation, ClientImportOperation, Finalizer, ImportSummary,
|
||||
LockImportRun, NewBlockState, StorageProvider,
|
||||
},
|
||||
cht,
|
||||
client::{
|
||||
BadBlocks, BlockBackend, BlockImportNotification, BlockOf, BlockchainEvents, ClientInfo,
|
||||
FinalityNotification, FinalityNotifications, ForkBlocks, ImportNotifications,
|
||||
ProvideUncles,
|
||||
},
|
||||
execution_extensions::ExecutionExtensions,
|
||||
light::ChangesProof,
|
||||
notifications::{StorageEventStream, StorageNotifications},
|
||||
CallExecutor, ExecutorProvider, KeyIterator, ProofProvider, UsageProvider,
|
||||
};
|
||||
@@ -56,39 +52,36 @@ use sp_api::{
|
||||
ProvideRuntimeApi,
|
||||
};
|
||||
use sp_blockchain::{
|
||||
self as blockchain, well_known_cache_keys::Id as CacheKeyId, Backend as ChainBackend, Cache,
|
||||
CachedHeaderMetadata, Error, HeaderBackend as ChainHeaderBackend, HeaderMetadata, ProvideCache,
|
||||
self as blockchain, well_known_cache_keys::Id as CacheKeyId, Backend as ChainBackend,
|
||||
CachedHeaderMetadata, Error, HeaderBackend as ChainHeaderBackend, HeaderMetadata,
|
||||
};
|
||||
use sp_consensus::{BlockOrigin, BlockStatus, Error as ConsensusError};
|
||||
|
||||
use sc_utils::mpsc::{tracing_unbounded, TracingUnboundedSender};
|
||||
use sp_core::{
|
||||
convert_hash,
|
||||
storage::{
|
||||
well_known_keys, ChildInfo, ChildType, PrefixedStorageKey, StorageChild, StorageData,
|
||||
StorageKey,
|
||||
},
|
||||
ChangesTrieConfiguration, NativeOrEncoded,
|
||||
NativeOrEncoded,
|
||||
};
|
||||
#[cfg(feature = "test-helpers")]
|
||||
use sp_keystore::SyncCryptoStorePtr;
|
||||
use sp_runtime::{
|
||||
generic::{BlockId, DigestItem, SignedBlock},
|
||||
generic::{BlockId, SignedBlock},
|
||||
traits::{
|
||||
Block as BlockT, DigestFor, HashFor, Header as HeaderT, NumberFor, One,
|
||||
SaturatedConversion, Zero,
|
||||
Block as BlockT, HashFor, Header as HeaderT, NumberFor, One, SaturatedConversion, Zero,
|
||||
},
|
||||
BuildStorage, Justification, Justifications,
|
||||
BuildStorage, Digest, Justification, Justifications,
|
||||
};
|
||||
use sp_state_machine::{
|
||||
key_changes, key_changes_proof, prove_child_read, prove_range_read_with_child_with_size,
|
||||
prove_read, read_range_proof_check_with_child_on_proving_backend, Backend as StateBackend,
|
||||
ChangesTrieAnchorBlockId, ChangesTrieConfigurationRange, ChangesTrieRootsStorage,
|
||||
ChangesTrieStorage, DBValue, KeyValueStates, KeyValueStorageLevel, MAX_NESTED_TRIE_DEPTH,
|
||||
prove_child_read, prove_range_read_with_child_with_size, prove_read,
|
||||
read_range_proof_check_with_child_on_proving_backend, Backend as StateBackend, KeyValueStates,
|
||||
KeyValueStorageLevel, MAX_NESTED_TRIE_DEPTH,
|
||||
};
|
||||
use sp_trie::{CompactProof, StorageProof};
|
||||
use std::{
|
||||
collections::{BTreeMap, HashMap, HashSet},
|
||||
collections::{HashMap, HashSet},
|
||||
marker::PhantomData,
|
||||
panic::UnwindSafe,
|
||||
path::PathBuf,
|
||||
@@ -413,250 +406,6 @@ where
|
||||
self.executor.runtime_version(id)
|
||||
}
|
||||
|
||||
/// 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: NumberFor<Block>,
|
||||
) -> sp_blockchain::Result<(Block::Header, StorageProof)> {
|
||||
let proof_error = || {
|
||||
sp_blockchain::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 mut current_num = cht_start;
|
||||
let cht_range = ::std::iter::from_fn(|| {
|
||||
let old_current_num = current_num;
|
||||
current_num = current_num + One::one();
|
||||
Some(old_current_num)
|
||||
});
|
||||
let headers = cht_range.map(|num| self.block_hash(num));
|
||||
let proof = cht::build_proof::<Block::Header, HashFor<Block>, _, _>(
|
||||
cht_size,
|
||||
cht_num,
|
||||
std::iter::once(block_num),
|
||||
headers,
|
||||
)?;
|
||||
Ok((header, proof))
|
||||
}
|
||||
|
||||
/// Does the same work as `key_changes_proof`, but assumes that CHTs are of passed size.
|
||||
pub fn key_changes_proof_with_cht_size(
|
||||
&self,
|
||||
first: Block::Hash,
|
||||
last: Block::Hash,
|
||||
min: Block::Hash,
|
||||
max: Block::Hash,
|
||||
storage_key: Option<&PrefixedStorageKey>,
|
||||
key: &StorageKey,
|
||||
cht_size: NumberFor<Block>,
|
||||
) -> sp_blockchain::Result<ChangesProof<Block::Header>> {
|
||||
struct AccessedRootsRecorder<'a, Block: BlockT> {
|
||||
storage: &'a dyn ChangesTrieStorage<HashFor<Block>, NumberFor<Block>>,
|
||||
min: NumberFor<Block>,
|
||||
required_roots_proofs: Mutex<BTreeMap<NumberFor<Block>, Block::Hash>>,
|
||||
}
|
||||
|
||||
impl<'a, Block: BlockT> ChangesTrieRootsStorage<HashFor<Block>, NumberFor<Block>>
|
||||
for AccessedRootsRecorder<'a, Block>
|
||||
{
|
||||
fn build_anchor(
|
||||
&self,
|
||||
hash: Block::Hash,
|
||||
) -> Result<ChangesTrieAnchorBlockId<Block::Hash, NumberFor<Block>>, String> {
|
||||
self.storage.build_anchor(hash)
|
||||
}
|
||||
|
||||
fn root(
|
||||
&self,
|
||||
anchor: &ChangesTrieAnchorBlockId<Block::Hash, NumberFor<Block>>,
|
||||
block: NumberFor<Block>,
|
||||
) -> Result<Option<Block::Hash>, String> {
|
||||
let root = self.storage.root(anchor, block)?;
|
||||
if block < self.min {
|
||||
if let Some(ref root) = root {
|
||||
self.required_roots_proofs.lock().insert(block, root.clone());
|
||||
}
|
||||
}
|
||||
Ok(root)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Block: BlockT> ChangesTrieStorage<HashFor<Block>, NumberFor<Block>>
|
||||
for AccessedRootsRecorder<'a, Block>
|
||||
{
|
||||
fn as_roots_storage(
|
||||
&self,
|
||||
) -> &dyn sp_state_machine::ChangesTrieRootsStorage<HashFor<Block>, NumberFor<Block>> {
|
||||
self
|
||||
}
|
||||
|
||||
fn with_cached_changed_keys(
|
||||
&self,
|
||||
root: &Block::Hash,
|
||||
functor: &mut dyn FnMut(&HashMap<Option<PrefixedStorageKey>, HashSet<Vec<u8>>>),
|
||||
) -> bool {
|
||||
self.storage.with_cached_changed_keys(root, functor)
|
||||
}
|
||||
|
||||
fn get(&self, key: &Block::Hash, prefix: Prefix) -> Result<Option<DBValue>, String> {
|
||||
self.storage.get(key, prefix)
|
||||
}
|
||||
}
|
||||
|
||||
let first_number =
|
||||
self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(first))?;
|
||||
let (storage, configs) = self.require_changes_trie(first_number, last, true)?;
|
||||
let min_number =
|
||||
self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(min))?;
|
||||
|
||||
let recording_storage = AccessedRootsRecorder::<Block> {
|
||||
storage: storage.storage(),
|
||||
min: min_number,
|
||||
required_roots_proofs: Mutex::new(BTreeMap::new()),
|
||||
};
|
||||
|
||||
let max_number = std::cmp::min(
|
||||
self.backend.blockchain().info().best_number,
|
||||
self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(max))?,
|
||||
);
|
||||
|
||||
// fetch key changes proof
|
||||
let mut proof = Vec::new();
|
||||
for (config_zero, config_end, config) in configs {
|
||||
let last_number =
|
||||
self.backend.blockchain().expect_block_number_from_id(&BlockId::Hash(last))?;
|
||||
let config_range = ChangesTrieConfigurationRange {
|
||||
config: &config,
|
||||
zero: config_zero,
|
||||
end: config_end.map(|(config_end_number, _)| config_end_number),
|
||||
};
|
||||
let proof_range = key_changes_proof::<HashFor<Block>, _>(
|
||||
config_range,
|
||||
&recording_storage,
|
||||
first_number,
|
||||
&ChangesTrieAnchorBlockId { hash: convert_hash(&last), number: last_number },
|
||||
max_number,
|
||||
storage_key,
|
||||
&key.0,
|
||||
)
|
||||
.map_err(|err| sp_blockchain::Error::ChangesTrieAccessFailed(err))?;
|
||||
proof.extend(proof_range);
|
||||
}
|
||||
|
||||
// now gather proofs for all changes tries roots that were touched during key_changes_proof
|
||||
// execution AND are unknown (i.e. replaced with CHT) to the requester
|
||||
let roots = recording_storage.required_roots_proofs.into_inner();
|
||||
let roots_proof = self.changes_trie_roots_proof(cht_size, roots.keys().cloned())?;
|
||||
|
||||
Ok(ChangesProof {
|
||||
max_block: max_number,
|
||||
proof,
|
||||
roots: roots.into_iter().map(|(n, h)| (n, convert_hash(&h))).collect(),
|
||||
roots_proof,
|
||||
})
|
||||
}
|
||||
|
||||
/// Generate CHT-based proof for roots of changes tries at given blocks.
|
||||
fn changes_trie_roots_proof<I: IntoIterator<Item = NumberFor<Block>>>(
|
||||
&self,
|
||||
cht_size: NumberFor<Block>,
|
||||
blocks: I,
|
||||
) -> sp_blockchain::Result<StorageProof> {
|
||||
// most probably we have touched several changes tries that are parts of the single CHT
|
||||
// => GroupBy changes tries by CHT number and then gather proof for the whole group at once
|
||||
let mut proofs = Vec::new();
|
||||
|
||||
cht::for_each_cht_group::<Block::Header, _, _, _>(
|
||||
cht_size,
|
||||
blocks,
|
||||
|_, cht_num, cht_blocks| {
|
||||
let cht_proof =
|
||||
self.changes_trie_roots_proof_at_cht(cht_size, cht_num, cht_blocks)?;
|
||||
proofs.push(cht_proof);
|
||||
Ok(())
|
||||
},
|
||||
(),
|
||||
)?;
|
||||
|
||||
Ok(StorageProof::merge(proofs))
|
||||
}
|
||||
|
||||
/// Generates CHT-based proof for roots of changes tries at given blocks
|
||||
/// (that are part of single CHT).
|
||||
fn changes_trie_roots_proof_at_cht(
|
||||
&self,
|
||||
cht_size: NumberFor<Block>,
|
||||
cht_num: NumberFor<Block>,
|
||||
blocks: Vec<NumberFor<Block>>,
|
||||
) -> sp_blockchain::Result<StorageProof> {
|
||||
let cht_start = cht::start_number(cht_size, cht_num);
|
||||
let mut current_num = cht_start;
|
||||
let cht_range = ::std::iter::from_fn(|| {
|
||||
let old_current_num = current_num;
|
||||
current_num = current_num + One::one();
|
||||
Some(old_current_num)
|
||||
});
|
||||
let roots = cht_range.map(|num| {
|
||||
self.header(&BlockId::Number(num)).map(|block| {
|
||||
block
|
||||
.and_then(|block| block.digest().log(DigestItem::as_changes_trie_root).cloned())
|
||||
})
|
||||
});
|
||||
let proof = cht::build_proof::<Block::Header, HashFor<Block>, _, _>(
|
||||
cht_size, cht_num, blocks, roots,
|
||||
)?;
|
||||
Ok(proof)
|
||||
}
|
||||
|
||||
/// Returns changes trie storage and all configurations that have been active
|
||||
/// in the range [first; last].
|
||||
///
|
||||
/// Configurations are returned in descending order (and obviously never overlap).
|
||||
/// If fail_if_disabled is false, returns maximal consequent configurations ranges,
|
||||
/// starting from last and stopping on either first, or when CT have been disabled.
|
||||
/// If fail_if_disabled is true, fails when there's a subrange where CT have been disabled
|
||||
/// inside first..last blocks range.
|
||||
fn require_changes_trie(
|
||||
&self,
|
||||
first: NumberFor<Block>,
|
||||
last: Block::Hash,
|
||||
fail_if_disabled: bool,
|
||||
) -> sp_blockchain::Result<(
|
||||
&dyn PrunableStateChangesTrieStorage<Block>,
|
||||
Vec<(NumberFor<Block>, Option<(NumberFor<Block>, Block::Hash)>, ChangesTrieConfiguration)>,
|
||||
)> {
|
||||
let storage = self
|
||||
.backend
|
||||
.changes_trie_storage()
|
||||
.ok_or_else(|| sp_blockchain::Error::ChangesTriesNotSupported)?;
|
||||
|
||||
let mut configs = Vec::with_capacity(1);
|
||||
let mut current = last;
|
||||
loop {
|
||||
let config_range = storage.configuration_at(&BlockId::Hash(current))?;
|
||||
match config_range.config {
|
||||
Some(config) => configs.push((config_range.zero.0, config_range.end, config)),
|
||||
None if !fail_if_disabled => return Ok((storage, configs)),
|
||||
None => return Err(sp_blockchain::Error::ChangesTriesNotSupported),
|
||||
}
|
||||
|
||||
if config_range.zero.0 < first {
|
||||
break
|
||||
}
|
||||
|
||||
current = *self
|
||||
.backend
|
||||
.blockchain()
|
||||
.expect_header(BlockId::Hash(config_range.zero.1))?
|
||||
.parent_hash();
|
||||
}
|
||||
|
||||
Ok((storage, configs))
|
||||
}
|
||||
|
||||
/// Apply a checked and validated block to an operation. If a justification is provided
|
||||
/// then `finalized` *must* be true.
|
||||
fn apply_block(
|
||||
@@ -811,7 +560,7 @@ where
|
||||
sc_consensus::StorageChanges::Changes(storage_changes) => {
|
||||
self.backend
|
||||
.begin_state_operation(&mut operation.op, BlockId::Hash(parent_hash))?;
|
||||
let (main_sc, child_sc, offchain_sc, tx, _, changes_trie_tx, tx_index) =
|
||||
let (main_sc, child_sc, offchain_sc, tx, _, tx_index) =
|
||||
storage_changes.into_inner();
|
||||
|
||||
if self.config.offchain_indexing_api {
|
||||
@@ -822,9 +571,6 @@ where
|
||||
operation.op.update_storage(main_sc.clone(), child_sc.clone())?;
|
||||
operation.op.update_transaction_index(tx_index)?;
|
||||
|
||||
if let Some(changes_trie_transaction) = changes_trie_tx {
|
||||
operation.op.update_changes_trie(changes_trie_transaction)?;
|
||||
}
|
||||
Some((main_sc, child_sc))
|
||||
},
|
||||
sc_consensus::StorageChanges::Import(changes) => {
|
||||
@@ -1003,11 +749,8 @@ where
|
||||
)?;
|
||||
|
||||
let state = self.backend.state_at(at)?;
|
||||
let changes_trie_state =
|
||||
changes_tries_state_at_block(&at, self.backend.changes_trie_storage())?;
|
||||
|
||||
let gen_storage_changes = runtime_api
|
||||
.into_storage_changes(&state, changes_trie_state.as_ref(), *parent_hash)
|
||||
.into_storage_changes(&state, *parent_hash)
|
||||
.map_err(sp_blockchain::Error::Storage)?;
|
||||
|
||||
if import_block.header.state_root() != &gen_storage_changes.transaction_storage_root
|
||||
@@ -1356,25 +1099,6 @@ where
|
||||
.map(|(r, p)| (r, StorageProof::merge(vec![p, code_proof])))
|
||||
}
|
||||
|
||||
fn header_proof(
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
) -> sp_blockchain::Result<(Block::Header, StorageProof)> {
|
||||
self.header_proof_with_cht_size(id, cht::size())
|
||||
}
|
||||
|
||||
fn key_changes_proof(
|
||||
&self,
|
||||
first: Block::Hash,
|
||||
last: Block::Hash,
|
||||
min: Block::Hash,
|
||||
max: Block::Hash,
|
||||
storage_key: Option<&PrefixedStorageKey>,
|
||||
key: &StorageKey,
|
||||
) -> sp_blockchain::Result<ChangesProof<Block::Header>> {
|
||||
self.key_changes_proof_with_cht_size(first, last, min, max, storage_key, key, cht::size())
|
||||
}
|
||||
|
||||
fn read_proof_collection(
|
||||
&self,
|
||||
id: &BlockId<Block>,
|
||||
@@ -1540,7 +1264,7 @@ where
|
||||
fn new_block_at<R: Into<RecordProof>>(
|
||||
&self,
|
||||
parent: &BlockId<Block>,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
inherent_digests: Digest,
|
||||
record_proof: R,
|
||||
) -> sp_blockchain::Result<sc_block_builder::BlockBuilder<Block, Self, B>> {
|
||||
sc_block_builder::BlockBuilder::new(
|
||||
@@ -1555,7 +1279,7 @@ where
|
||||
|
||||
fn new_block(
|
||||
&self,
|
||||
inherent_digests: DigestFor<Block>,
|
||||
inherent_digests: Digest,
|
||||
) -> sp_blockchain::Result<sc_block_builder::BlockBuilder<Block, Self, B>> {
|
||||
let info = self.chain_info();
|
||||
sc_block_builder::BlockBuilder::new(
|
||||
@@ -1703,89 +1427,6 @@ where
|
||||
.child_storage_hash(child_info, &key.0)
|
||||
.map_err(|e| sp_blockchain::Error::from_state(Box::new(e)))?)
|
||||
}
|
||||
|
||||
fn max_key_changes_range(
|
||||
&self,
|
||||
first: NumberFor<Block>,
|
||||
last: BlockId<Block>,
|
||||
) -> sp_blockchain::Result<Option<(NumberFor<Block>, BlockId<Block>)>> {
|
||||
let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?;
|
||||
let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?;
|
||||
if first > last_number {
|
||||
return Err(sp_blockchain::Error::ChangesTrieAccessFailed(
|
||||
"Invalid changes trie range".into(),
|
||||
))
|
||||
}
|
||||
|
||||
let (storage, configs) = match self.require_changes_trie(first, last_hash, false).ok() {
|
||||
Some((storage, configs)) => (storage, configs),
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let first_available_changes_trie = configs.last().map(|config| config.0);
|
||||
match first_available_changes_trie {
|
||||
Some(first_available_changes_trie) => {
|
||||
let oldest_unpruned = storage.oldest_pruned_digest_range_end();
|
||||
let first = std::cmp::max(first_available_changes_trie, oldest_unpruned);
|
||||
Ok(Some((first, last)))
|
||||
},
|
||||
None => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
fn key_changes(
|
||||
&self,
|
||||
first: NumberFor<Block>,
|
||||
last: BlockId<Block>,
|
||||
storage_key: Option<&PrefixedStorageKey>,
|
||||
key: &StorageKey,
|
||||
) -> sp_blockchain::Result<Vec<(NumberFor<Block>, u32)>> {
|
||||
let last_number = self.backend.blockchain().expect_block_number_from_id(&last)?;
|
||||
let last_hash = self.backend.blockchain().expect_block_hash_from_id(&last)?;
|
||||
let (storage, configs) = self.require_changes_trie(first, last_hash, true)?;
|
||||
|
||||
let mut result = Vec::new();
|
||||
let best_number = self.backend.blockchain().info().best_number;
|
||||
for (config_zero, config_end, config) in configs {
|
||||
let range_first = ::std::cmp::max(first, config_zero + One::one());
|
||||
let range_anchor = match config_end {
|
||||
Some((config_end_number, config_end_hash)) =>
|
||||
if last_number > config_end_number {
|
||||
ChangesTrieAnchorBlockId {
|
||||
hash: config_end_hash,
|
||||
number: config_end_number,
|
||||
}
|
||||
} else {
|
||||
ChangesTrieAnchorBlockId {
|
||||
hash: convert_hash(&last_hash),
|
||||
number: last_number,
|
||||
}
|
||||
},
|
||||
None =>
|
||||
ChangesTrieAnchorBlockId { hash: convert_hash(&last_hash), number: last_number },
|
||||
};
|
||||
|
||||
let config_range = ChangesTrieConfigurationRange {
|
||||
config: &config,
|
||||
zero: config_zero.clone(),
|
||||
end: config_end.map(|(config_end_number, _)| config_end_number),
|
||||
};
|
||||
let result_range: Vec<(NumberFor<Block>, u32)> = key_changes::<HashFor<Block>, _>(
|
||||
config_range,
|
||||
storage.storage(),
|
||||
range_first,
|
||||
&range_anchor,
|
||||
best_number,
|
||||
storage_key,
|
||||
&key.0,
|
||||
)
|
||||
.and_then(|r| r.map(|r| r.map(|(block, tx)| (block, tx))).collect::<Result<_, _>>())
|
||||
.map_err(|err| sp_blockchain::Error::ChangesTrieAccessFailed(err))?;
|
||||
result.extend(result_range);
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E, Block, RA> HeaderMetadata<Block> for Client<B, E, Block, RA>
|
||||
@@ -1913,16 +1554,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E, Block, RA> ProvideCache<Block> for Client<B, E, Block, RA>
|
||||
where
|
||||
B: backend::Backend<Block>,
|
||||
Block: BlockT,
|
||||
{
|
||||
fn cache(&self) -> Option<Arc<dyn Cache<Block>>> {
|
||||
self.backend.blockchain().cache()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B, E, Block, RA> ProvideRuntimeApi<Block> for Client<B, E, Block, RA>
|
||||
where
|
||||
B: backend::Backend<Block>,
|
||||
|
||||
@@ -68,7 +68,7 @@ use sc_client_api::{blockchain::HeaderBackend, BlockchainEvents};
|
||||
pub use sc_consensus::ImportQueue;
|
||||
pub use sc_executor::NativeExecutionDispatch;
|
||||
#[doc(hidden)]
|
||||
pub use sc_network::config::{OnDemand, TransactionImport, TransactionImportFuture};
|
||||
pub use sc_network::config::{TransactionImport, TransactionImportFuture};
|
||||
pub use sc_rpc::Metadata as RpcMetadata;
|
||||
pub use sc_tracing::TracingReceiver;
|
||||
pub use sc_transaction_pool::Options as TransactionPoolOptions;
|
||||
|
||||
Reference in New Issue
Block a user