feat/ocw/bookkeeping (#5200)

Co-Authored-By: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
This commit is contained in:
Bernhard Schuster
2020-04-24 16:46:19 +02:00
committed by GitHub
parent f66168505b
commit 72ee7d5797
40 changed files with 675 additions and 80 deletions
+9 -1
View File
@@ -19,7 +19,7 @@
use std::sync::Arc;
use std::collections::HashMap;
use sp_core::ChangesTrieConfigurationRange;
use sp_core::offchain::OffchainStorage;
use sp_core::offchain::{OffchainStorage,storage::OffchainOverlayedChanges};
use sp_runtime::{generic::BlockId, Justification, Storage};
use sp_runtime::traits::{Block as BlockT, NumberFor, HashFor};
use sp_state_machine::{
@@ -148,6 +148,14 @@ pub trait BlockImportOperation<Block: BlockT> {
child_update: ChildStorageCollection,
) -> sp_blockchain::Result<()>;
/// Write offchain storage changes to the database.
fn update_offchain_storage(
&mut self,
_offchain_update: OffchainOverlayedChanges,
) -> sp_blockchain::Result<()> {
Ok(())
}
/// Inject changes trie data into the database.
fn update_changes_trie(
&mut self,
+2 -1
View File
@@ -26,7 +26,7 @@ use sp_state_machine::{
};
use sc_executor::{RuntimeVersion, NativeVersion};
use sp_externalities::Extensions;
use sp_core::NativeOrEncoded;
use sp_core::{NativeOrEncoded,offchain::storage::OffchainOverlayedChanges};
use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache};
use crate::execution_extensions::ExecutionExtensions;
@@ -84,6 +84,7 @@ pub trait CallExecutor<B: BlockT> {
method: &str,
call_data: &[u8],
changes: &RefCell<OverlayedChanges>,
offchain_changes: &RefCell<OffchainOverlayedChanges>,
storage_transaction_cache: Option<&RefCell<
StorageTransactionCache<B, <Self::Backend as crate::backend::Backend<B>>::State>,
>>,
@@ -177,7 +177,7 @@ impl<Block: traits::Block> ExecutionExtensions<Block> {
if let ExecutionContext::OffchainCall(Some(ext)) = context {
extensions.register(
OffchainExt::new(offchain::LimitedExternalities::new(capabilities, ext.0))
)
);
}
(manager, extensions)
+12
View File
@@ -136,6 +136,18 @@ arg_enum! {
}
}
arg_enum! {
/// Whether off-chain workers are enabled.
#[allow(missing_docs)]
#[derive(Debug, Clone)]
pub enum OffchainWorkerEnabled {
Always,
Never,
WhenValidating,
}
}
/// Default value for the `--execution-syncing` parameter.
pub const DEFAULT_EXECUTION_SYNCING: ExecutionStrategy = ExecutionStrategy::NativeElseWasm;
/// Default value for the `--execution-import-block` parameter.
+7 -1
View File
@@ -144,6 +144,12 @@ macro_rules! substrate_cli_subcommands {
}
}
fn offchain_worker_params(&self) -> Option<&$crate::OffchainWorkerParams> {
match self {
$($enum::$variant(cmd) => cmd.offchain_worker_params()),*
}
}
fn base_path(&self) -> $crate::Result<::std::option::Option<::std::path::PathBuf>> {
match self {
$($enum::$variant(cmd) => cmd.base_path()),*
@@ -327,7 +333,7 @@ macro_rules! substrate_cli_subcommands {
}
}
fn offchain_worker(&self, role: &::sc_service::Role) -> $crate::Result<bool> {
fn offchain_worker(&self, role: &::sc_service::Role) -> $crate::Result<::sc_service::config::OffchainWorkerConfig> {
match self {
$($enum::$variant(cmd) => cmd.offchain_worker(role)),*
}
+9 -32
View File
@@ -20,6 +20,7 @@ use crate::params::KeystoreParams;
use crate::params::NetworkParams;
use crate::params::SharedParams;
use crate::params::TransactionPoolParams;
use crate::params::OffchainWorkerParams;
use crate::CliConfiguration;
use regex::Regex;
use sc_service::{
@@ -28,18 +29,7 @@ use sc_service::{
};
use sc_telemetry::TelemetryEndpoints;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use structopt::{clap::arg_enum, StructOpt};
arg_enum! {
/// Whether off-chain workers are enabled.
#[allow(missing_docs)]
#[derive(Debug, Clone)]
pub enum OffchainWorkerEnabled {
Always,
Never,
WhenValidating,
}
}
use structopt::StructOpt;
/// The `run` command used to run a node.
#[derive(Debug, StructOpt, Clone)]
@@ -173,17 +163,9 @@ pub struct RunCmd {
#[structopt(long = "telemetry-url", value_name = "URL VERBOSITY", parse(try_from_str = parse_telemetry_endpoints))]
pub telemetry_endpoints: Vec<(String, u8)>,
/// Should execute offchain workers on every block.
///
/// By default it's only enabled for nodes that are authoring new blocks.
#[structopt(
long = "offchain-worker",
value_name = "ENABLED",
possible_values = &OffchainWorkerEnabled::variants(),
case_insensitive = true,
default_value = "WhenValidating"
)]
pub offchain_worker: OffchainWorkerEnabled,
#[allow(missing_docs)]
#[structopt(flatten)]
pub offchain_worker_params: OffchainWorkerParams,
#[allow(missing_docs)]
#[structopt(flatten)]
@@ -300,6 +282,10 @@ impl CliConfiguration for RunCmd {
Some(&self.keystore_params)
}
fn offchain_worker_params(&self) -> Option<&OffchainWorkerParams> {
Some(&self.offchain_worker_params)
}
fn node_name(&self) -> Result<String> {
let name: String = match (self.name.as_ref(), self.get_keyring()) {
(Some(name), _) => name.to_string(),
@@ -439,15 +425,6 @@ impl CliConfiguration for RunCmd {
Ok(self.unsafe_rpc_expose)
}
fn offchain_worker(&self, role: &Role) -> Result<bool> {
Ok(match (&self.offchain_worker, role) {
(OffchainWorkerEnabled::WhenValidating, Role::Authority { .. }) => true,
(OffchainWorkerEnabled::Always, _) => true,
(OffchainWorkerEnabled::Never, _) => false,
(OffchainWorkerEnabled::WhenValidating, _) => false,
})
}
fn transaction_pool(&self) -> Result<TransactionPoolOptions> {
Ok(self.pool_config.transaction_pool())
}
+14 -7
View File
@@ -19,15 +19,15 @@
use crate::error::Result;
use crate::{
init_logger, ImportParams, KeystoreParams, NetworkParams, NodeKeyParams,
PruningParams, SharedParams, SubstrateCli,
OffchainWorkerParams, PruningParams, SharedParams, SubstrateCli,
};
use crate::arg_enums::Database;
use app_dirs::{AppDataType, AppInfo};
use names::{Generator, Name};
use sc_service::config::{
Configuration, DatabaseConfig, ExecutionStrategies, ExtTransport, KeystoreConfig,
NetworkConfiguration, NodeKeyConfig, PrometheusConfig, PruningMode, Role, TelemetryEndpoints,
TransactionPoolOptions, WasmExecutionMethod,
NetworkConfiguration, NodeKeyConfig, OffchainWorkerConfig, PrometheusConfig, PruningMode,
Role, TelemetryEndpoints, TransactionPoolOptions, WasmExecutionMethod,
};
use sc_service::{ChainSpec, TracingReceiver};
use std::future::Future;
@@ -67,6 +67,11 @@ pub trait CliConfiguration: Sized {
None
}
/// Get a reference to `OffchainWorkerParams` for this object.
fn offchain_worker_params(&self) -> Option<&OffchainWorkerParams> {
None
}
/// Get the NodeKeyParams for this object
fn node_key_params(&self) -> Option<&NodeKeyParams> {
self.network_params()
@@ -301,11 +306,13 @@ pub trait CliConfiguration: Sized {
Ok(Default::default())
}
/// Returns `Ok(true)` if offchain worker should be used
/// Returns an offchain worker config wrapped in `Ok(_)`
///
/// By default this is `false`.
fn offchain_worker(&self, _role: &Role) -> Result<bool> {
Ok(Default::default())
/// By default offchain workers are disabled.
fn offchain_worker(&self, role: &Role) -> Result<OffchainWorkerConfig> {
self.offchain_worker_params()
.map(|x| x.offchain_worker(role))
.unwrap_or_else(|| { Ok(OffchainWorkerConfig::default()) })
}
/// Returns `Ok(true)` if authoring should be forced
+2
View File
@@ -21,6 +21,7 @@ mod node_key_params;
mod pruning_params;
mod shared_params;
mod transaction_pool_params;
mod offchain_worker_params;
use std::fmt::Debug;
use std::str::FromStr;
@@ -29,6 +30,7 @@ pub use crate::params::import_params::*;
pub use crate::params::keystore_params::*;
pub use crate::params::network_params::*;
pub use crate::params::node_key_params::*;
pub use crate::params::offchain_worker_params::*;
pub use crate::params::pruning_params::*;
pub use crate::params::shared_params::*;
pub use crate::params::transaction_pool_params::*;
@@ -0,0 +1,77 @@
// Copyright 2020 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Offchain worker related configuration parameters.
//!
//! A subset of configuration parameters which are relevant to
//! the inner working of offchain workers. The usage is solely
//! targeted at handling input parameter parsing providing
//! a reasonable abstraction.
use structopt::StructOpt;
use sc_service::config::OffchainWorkerConfig;
use sc_network::config::Role;
use crate::error;
use crate::OffchainWorkerEnabled;
/// Offchain worker related parameters.
#[derive(Debug, StructOpt, Clone)]
pub struct OffchainWorkerParams {
/// Should execute offchain workers on every block.
///
/// By default it's only enabled for nodes that are authoring new blocks.
#[structopt(
long = "offchain-worker",
value_name = "ENABLED",
possible_values = &OffchainWorkerEnabled::variants(),
case_insensitive = true,
default_value = "WhenValidating"
)]
pub enabled: OffchainWorkerEnabled,
/// Enable Offchain Indexing API, which allows block import to write to Offchain DB.
///
/// Enables a runtime to write directly to a offchain workers
/// DB during block import.
#[structopt(
long = "enable-offchain-indexing",
value_name = "ENABLE_OFFCHAIN_INDEXING"
)]
pub indexing_enabled: bool,
}
impl OffchainWorkerParams {
/// Load spec to `Configuration` from `OffchainWorkerParams` and spec factory.
pub fn offchain_worker(
&self,
role: &Role,
) -> error::Result<OffchainWorkerConfig>
{
let enabled = match (&self.enabled, role) {
(OffchainWorkerEnabled::WhenValidating, Role::Authority { .. }) => true,
(OffchainWorkerEnabled::Always, _) => true,
(OffchainWorkerEnabled::Never, _) => false,
(OffchainWorkerEnabled::WhenValidating, _) => false,
};
let indexing_enabled = enabled && self.indexing_enabled;
Ok(OffchainWorkerConfig { enabled, indexing_enabled })
}
}
+25 -1
View File
@@ -50,6 +50,7 @@ use std::path::{Path, PathBuf};
use std::io;
use std::collections::HashMap;
use sc_client_api::{
ForkBlocks, UsageInfo, MemoryInfo, BadBlocks, IoInfo, MemorySize, CloneableSpawn,
execution_extensions::ExecutionExtensions,
@@ -65,6 +66,7 @@ use sp_trie::{MemoryDB, PrefixedMemoryDB, prefixed_key};
use sp_database::Transaction;
use parking_lot::RwLock;
use sp_core::{ChangesTrieConfiguration, traits::CodeExecutor};
use sp_core::offchain::storage::{OffchainOverlayedChange,OffchainOverlayedChanges};
use sp_core::storage::{well_known_keys, ChildInfo};
use sp_runtime::{
generic::BlockId, Justification, Storage,
@@ -324,6 +326,7 @@ pub fn new_client<E, Block, RA>(
execution_extensions: ExecutionExtensions<Block>,
spawn_handle: Box<dyn CloneableSpawn>,
prometheus_registry: Option<Registry>,
config: sc_client::ClientConfig,
) -> Result<(
sc_client::Client<
Backend<Block>,
@@ -340,7 +343,7 @@ pub fn new_client<E, Block, RA>(
E: CodeExecutor + RuntimeInfo,
{
let backend = Arc::new(Backend::new(settings, CANONICALIZATION_DELAY)?);
let executor = sc_client::LocalCallExecutor::new(backend.clone(), executor, spawn_handle);
let executor = sc_client::LocalCallExecutor::new(backend.clone(), executor, spawn_handle, config.clone());
Ok((
sc_client::Client::new(
backend.clone(),
@@ -350,6 +353,7 @@ pub fn new_client<E, Block, RA>(
bad_blocks,
execution_extensions,
prometheus_registry,
config,
)?,
backend,
))
@@ -558,6 +562,7 @@ pub struct BlockImportOperation<Block: BlockT> {
db_updates: PrefixedMemoryDB<HashFor<Block>>,
storage_updates: StorageCollection,
child_storage_updates: ChildStorageCollection,
offchain_storage_updates: OffchainOverlayedChanges,
changes_trie_updates: MemoryDB<HashFor<Block>>,
changes_trie_build_cache_update: Option<ChangesTrieCacheAction<Block::Hash, NumberFor<Block>>>,
changes_trie_config_update: Option<Option<ChangesTrieConfiguration>>,
@@ -569,6 +574,15 @@ pub struct BlockImportOperation<Block: BlockT> {
}
impl<Block: BlockT> BlockImportOperation<Block> {
fn apply_offchain(&mut self, transaction: &mut Transaction<DbHash>) {
for (key, value_operation) in self.offchain_storage_updates.drain() {
match value_operation {
OffchainOverlayedChange::SetValue(val) => transaction.set_from_vec(columns::OFFCHAIN, &key, val),
OffchainOverlayedChange::Remove => transaction.remove(columns::OFFCHAIN, &key),
}
}
}
fn apply_aux(&mut self, transaction: &mut Transaction<DbHash>) {
for (key, maybe_val) in self.aux_ops.drain(..) {
match maybe_val {
@@ -675,6 +689,14 @@ impl<Block: BlockT> sc_client_api::backend::BlockImportOperation<Block> for Bloc
Ok(())
}
fn update_offchain_storage(
&mut self,
offchain_update: OffchainOverlayedChanges,
) -> ClientResult<()> {
self.offchain_storage_updates = offchain_update;
Ok(())
}
fn mark_finalized(
&mut self,
block: BlockId<Block>,
@@ -1017,6 +1039,7 @@ impl<Block: BlockT> Backend<Block> {
let mut finalization_displaced_leaves = None;
operation.apply_aux(&mut transaction);
operation.apply_offchain(&mut transaction);
let mut meta_updates = Vec::with_capacity(operation.finalized_blocks.len());
let mut last_finalized_hash = self.blockchain.meta.read().finalized_hash;
@@ -1360,6 +1383,7 @@ impl<Block: BlockT> sc_client_api::backend::Backend<Block> for Backend<Block> {
db_updates: PrefixedMemoryDB::default(),
storage_updates: Default::default(),
child_storage_updates: Default::default(),
offchain_storage_updates: Default::default(),
changes_trie_config_update: None,
changes_trie_updates: MemoryDB::default(),
changes_trie_build_cache_update: None,
@@ -183,6 +183,12 @@ sp_core::wasm_export_functions! {
}
}
fn test_offchain_index_set() {
sp_io::offchain_index::set(b"k", b"v");
}
fn test_offchain_local_storage() -> bool {
let kind = sp_core::offchain::StorageKind::PERSISTENT;
assert_eq!(sp_io::offchain::local_storage_get(kind, b"test"), None);
@@ -450,6 +450,28 @@ fn ordered_trie_root_should_work(wasm_method: WasmExecutionMethod) {
);
}
#[test_case(WasmExecutionMethod::Interpreted)]
#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))]
fn offchain_index(wasm_method: WasmExecutionMethod) {
let mut ext = TestExternalities::default();
let (offchain, _state) = testing::TestOffchainExt::new();
ext.register_extension(OffchainExt::new(offchain));
call_in_wasm(
"test_offchain_index_set",
&[0],
wasm_method,
&mut ext.ext(),
).unwrap();
use sp_core::offchain::storage::OffchainOverlayedChange;
assert_eq!(
ext.ext()
.get_offchain_storage_changes()
.get(sp_core::offchain::STORAGE_PREFIX, b"k"),
Some(OffchainOverlayedChange::SetValue(b"v".to_vec()))
);
}
#[test_case(WasmExecutionMethod::Interpreted)]
#[cfg_attr(feature = "wasmtime", test_case(WasmExecutionMethod::Compiled))]
fn offchain_local_storage_should_work(wasm_method: WasmExecutionMethod) {
+9 -5
View File
@@ -17,7 +17,7 @@
use crate::{Service, NetworkStatus, NetworkState, error::Error, DEFAULT_PROTOCOL_ID, MallocSizeOfWasm};
use crate::{start_rpc_servers, build_network_future, TransactionPoolAdapter, TaskManager};
use crate::status_sinks;
use crate::config::{Configuration, KeystoreConfig, PrometheusConfig};
use crate::config::{Configuration, KeystoreConfig, PrometheusConfig, OffchainWorkerConfig};
use crate::metrics::MetricsService;
use sc_client_api::{
self,
@@ -27,7 +27,7 @@ use sc_client_api::{
ExecutorProvider, CallExecutor
};
use sp_utils::mpsc::{tracing_unbounded, TracingUnboundedSender};
use sc_client::Client;
use sc_client::{Client, ClientConfig};
use sc_chain_spec::get_extension;
use sp_consensus::import_queue::ImportQueue;
use futures::{
@@ -215,6 +215,10 @@ fn new_full_parts<TBl, TRtApi, TExecDisp>(
extensions,
Box::new(task_manager.spawn_handle()),
config.prometheus_config.as_ref().map(|config| config.registry.clone()),
ClientConfig {
offchain_worker_enabled : config.offchain_worker.enabled ,
offchain_indexing_api: config.offchain_worker.indexing_enabled,
},
)?
};
@@ -834,11 +838,11 @@ ServiceBuilder<
let network_status_sinks = Arc::new(Mutex::new(status_sinks::StatusSinks::new()));
let offchain_storage = backend.offchain_storage();
let offchain_workers = match (config.offchain_worker, offchain_storage.clone()) {
(true, Some(db)) => {
let offchain_workers = match (config.offchain_worker.clone(), offchain_storage.clone()) {
(OffchainWorkerConfig {enabled: true, .. }, Some(db)) => {
Some(Arc::new(sc_offchain::OffchainWorkers::new(client.clone(), db)))
},
(true, None) => {
(OffchainWorkerConfig {enabled: true, .. }, None) => {
warn!("Offchain workers disabled, due to lack of offchain storage support in backend.");
None
},
+9 -1
View File
@@ -79,7 +79,7 @@ pub struct Configuration {
/// The default number of 64KB pages to allocate for Wasm execution
pub default_heap_pages: Option<u64>,
/// Should offchain workers be executed.
pub offchain_worker: bool,
pub offchain_worker: OffchainWorkerConfig,
/// Enable authoring even when offline.
pub force_authoring: bool,
/// Disable GRANDPA when running in validator mode
@@ -125,6 +125,14 @@ impl KeystoreConfig {
}
}
}
/// Configuration of the database of the client.
#[derive(Clone, Default)]
pub struct OffchainWorkerConfig {
/// If this is allowed.
pub enabled: bool,
/// allow writes from the runtime to the offchain worker database.
pub indexing_enabled: bool,
}
/// Configuration of the Prometheus endpoint.
#[derive(Clone)]
+1 -1
View File
@@ -195,7 +195,7 @@ fn node_config<G: RuntimeGenesis + 'static, E: ChainSpecExtension + Clone + 'sta
telemetry_endpoints: None,
telemetry_external_transport: None,
default_heap_pages: None,
offchain_worker: false,
offchain_worker: Default::default(),
force_authoring: false,
disable_grandpa: false,
dev_key_seed: key_seed,
+20 -3
View File
@@ -25,9 +25,10 @@ use sp_state_machine::{
};
use sc_executor::{RuntimeVersion, RuntimeInfo, NativeVersion};
use sp_externalities::Extensions;
use sp_core::{NativeOrEncoded, NeverNativeValue, traits::CodeExecutor};
use sp_core::{NativeOrEncoded, NeverNativeValue, traits::CodeExecutor, offchain::storage::OffchainOverlayedChanges};
use sp_api::{ProofRecorder, InitializeBlock, StorageTransactionCache};
use sc_client_api::{backend, call_executor::CallExecutor, CloneableSpawn};
use crate::client::ClientConfig;
/// Call executor that executes methods locally, querying all required
/// data from local backend.
@@ -35,6 +36,7 @@ pub struct LocalCallExecutor<B, E> {
backend: Arc<B>,
executor: E,
spawn_handle: Box<dyn CloneableSpawn>,
client_config: ClientConfig,
}
impl<B, E> LocalCallExecutor<B, E> {
@@ -43,11 +45,13 @@ impl<B, E> LocalCallExecutor<B, E> {
backend: Arc<B>,
executor: E,
spawn_handle: Box<dyn CloneableSpawn>,
client_config: ClientConfig,
) -> Self {
LocalCallExecutor {
backend,
executor,
spawn_handle,
client_config,
}
}
}
@@ -58,6 +62,7 @@ impl<B, E> Clone for LocalCallExecutor<B, E> where E: Clone {
backend: self.backend.clone(),
executor: self.executor.clone(),
spawn_handle: self.spawn_handle.clone(),
client_config: self.client_config.clone(),
}
}
}
@@ -81,6 +86,11 @@ where
extensions: Option<Extensions>,
) -> sp_blockchain::Result<Vec<u8>> {
let mut changes = OverlayedChanges::default();
let mut offchain_changes = if self.client_config.offchain_indexing_api {
OffchainOverlayedChanges::enabled()
} else {
OffchainOverlayedChanges::disabled()
};
let changes_trie = backend::changes_tries_state_at_block(
id, self.backend.changes_trie_storage()
)?;
@@ -90,6 +100,7 @@ where
&state,
changes_trie,
&mut changes,
&mut offchain_changes,
&self.executor,
method,
call_data,
@@ -120,6 +131,7 @@ where
method: &str,
call_data: &[u8],
changes: &RefCell<OverlayedChanges>,
offchain_changes: &RefCell<OffchainOverlayedChanges>,
storage_transaction_cache: Option<&RefCell<
StorageTransactionCache<Block, B::State>
>>,
@@ -143,6 +155,9 @@ where
let mut state = self.backend.state_at(*at)?;
let changes = &mut *changes.borrow_mut();
let offchain_changes = &mut *offchain_changes.borrow_mut();
match recorder {
Some(recorder) => {
let trie_state = state.as_trie_backend()
@@ -160,11 +175,11 @@ where
recorder.clone(),
);
let changes = &mut *changes.borrow_mut();
let mut state_machine = StateMachine::new(
&backend,
changes_trie_state,
changes,
offchain_changes,
&self.executor,
method,
call_data,
@@ -179,11 +194,11 @@ where
None => {
let state_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&state);
let runtime_code = state_runtime_code.runtime_code()?;
let changes = &mut *changes.borrow_mut();
let mut state_machine = StateMachine::new(
&state,
changes_trie_state,
changes,
offchain_changes,
&self.executor,
method,
call_data,
@@ -198,6 +213,7 @@ where
fn runtime_version(&self, id: &BlockId<Block>) -> sp_blockchain::Result<RuntimeVersion> {
let mut overlay = OverlayedChanges::default();
let mut offchain_overlay = OffchainOverlayedChanges::default();
let changes_trie_state = backend::changes_tries_state_at_block(
id,
self.backend.changes_trie_storage(),
@@ -206,6 +222,7 @@ where
let mut cache = StorageTransactionCache::<Block, B::State>::default();
let mut ext = Ext::new(
&mut overlay,
&mut offchain_overlay,
&mut cache,
&state,
changes_trie_state,
+45 -4
View File
@@ -99,6 +99,7 @@ pub struct Client<B, E, Block, RA> where Block: BlockT {
importing_block: RwLock<Option<Block::Hash>>,
block_rules: BlockRules<Block>,
execution_extensions: ExecutionExtensions<Block>,
config: ClientConfig,
_phantom: PhantomData<RA>,
}
@@ -136,6 +137,7 @@ pub fn new_in_mem<E, Block, S, RA>(
keystore: Option<sp_core::traits::BareCryptoStorePtr>,
prometheus_registry: Option<Registry>,
spawn_handle: Box<dyn CloneableSpawn>,
config: ClientConfig,
) -> sp_blockchain::Result<Client<
in_mem::Backend<Block>,
LocalCallExecutor<in_mem::Backend<Block>, E>,
@@ -146,7 +148,24 @@ pub fn new_in_mem<E, Block, S, RA>(
S: BuildStorage,
Block: BlockT,
{
new_with_backend(Arc::new(in_mem::Backend::new()), executor, genesis_storage, keystore, spawn_handle, prometheus_registry)
new_with_backend(
Arc::new(in_mem::Backend::new()),
executor,
genesis_storage,
keystore,
spawn_handle,
prometheus_registry,
config,
)
}
/// Relevant client configuration items relevant for the client.
#[derive(Debug,Clone,Default)]
pub struct ClientConfig {
/// Enable the offchain worker db.
pub offchain_worker_enabled: bool,
/// If true, allows access from the runtime to write into offchain worker db.
pub offchain_indexing_api: bool,
}
/// Create a client with the explicitly provided backend.
@@ -158,6 +177,7 @@ pub fn new_with_backend<B, E, Block, S, RA>(
keystore: Option<sp_core::traits::BareCryptoStorePtr>,
spawn_handle: Box<dyn CloneableSpawn>,
prometheus_registry: Option<Registry>,
config: ClientConfig,
) -> sp_blockchain::Result<Client<B, LocalCallExecutor<B, E>, Block, RA>>
where
E: CodeExecutor + RuntimeInfo,
@@ -165,7 +185,7 @@ pub fn new_with_backend<B, E, Block, S, RA>(
Block: BlockT,
B: backend::LocalBackend<Block> + 'static,
{
let call_executor = LocalCallExecutor::new(backend.clone(), executor, spawn_handle);
let call_executor = LocalCallExecutor::new(backend.clone(), executor, spawn_handle, config.clone());
let extensions = ExecutionExtensions::new(Default::default(), keystore);
Client::new(
backend,
@@ -175,6 +195,7 @@ pub fn new_with_backend<B, E, Block, S, RA>(
Default::default(),
extensions,
prometheus_registry,
config,
)
}
@@ -243,6 +264,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
B: backend::Backend<Block>,
E: CallExecutor<Block>,
Block: BlockT,
Block::Header: Clone,
{
/// Creates new Substrate Client with given blockchain and code executor.
pub fn new(
@@ -253,6 +275,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
bad_blocks: BadBlocks<Block>,
execution_extensions: ExecutionExtensions<Block>,
prometheus_registry: Option<Registry>,
config: ClientConfig,
) -> sp_blockchain::Result<Self> {
if backend.blockchain().header(BlockId::Number(Zero::zero()))?.is_none() {
let genesis_storage = build_genesis_storage.build_storage()?;
@@ -282,6 +305,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
importing_block: Default::default(),
block_rules: BlockRules::new(fork_blocks, bad_blocks),
execution_extensions,
config,
_phantom: Default::default(),
})
}
@@ -614,7 +638,7 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
if let Ok(ImportResult::Imported(ref aux)) = result {
if aux.is_new_best {
use rand::Rng;
// don't send telemetry block import events during initial sync for every
// block to avoid spamming the telemetry server, these events will be randomly
// sent at a rate of 1/10.
@@ -696,7 +720,22 @@ impl<B, E, Block, RA> Client<B, E, Block, RA> where
operation.op.update_cache(new_cache);
let (main_sc, child_sc, tx, _, changes_trie_tx) = storage_changes.into_inner();
let (
main_sc,
child_sc,
offchain_sc,
tx, _,
changes_trie_tx,
) = storage_changes.into_inner();
if self.config.offchain_indexing_api {
// if let Some(mut offchain_storage) = self.backend.offchain_storage() {
// offchain_sc.iter().for_each(|(k,v)| {
// offchain_storage.set(b"block-import-info", k,v)
// });
// }
operation.op.update_offchain_storage(offchain_sc)?;
}
operation.op.update_db_storage(tx)?;
operation.op.update_storage(main_sc.clone(), child_sc.clone())?;
@@ -1554,6 +1593,7 @@ impl<B, E, Block, RA> CallApiAt<Block> for Client<B, E, Block, RA> where
params.function,
&params.arguments,
params.overlayed_changes,
params.offchain_changes,
Some(params.storage_transaction_cache),
params.initialize_block,
manager,
@@ -3493,6 +3533,7 @@ pub(crate) mod tests {
None,
None,
sp_core::tasks::executor(),
Default::default(),
)
.unwrap();
+14
View File
@@ -55,6 +55,7 @@ mod tests {
};
use sp_runtime::traits::BlakeTwo256;
use sp_core::tasks::executor as tasks_executor;
use sp_core::offchain::storage::OffchainOverlayedChanges;
use hex_literal::*;
native_executor_instance!(
@@ -90,6 +91,7 @@ mod tests {
};
let hash = header.hash();
let mut overlay = OverlayedChanges::default();
let mut offchain_overlay = OffchainOverlayedChanges::default();
let backend_runtime_code = sp_state_machine::backend::BackendRuntimeCode::new(&backend);
let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend");
@@ -97,6 +99,7 @@ mod tests {
backend,
sp_state_machine::disabled_changes_trie_state::<_, u64>(),
&mut overlay,
&mut offchain_overlay,
&executor(),
"Core_initialize_block",
&header.encode(),
@@ -112,6 +115,7 @@ mod tests {
backend,
sp_state_machine::disabled_changes_trie_state::<_, u64>(),
&mut overlay,
&mut offchain_overlay,
&executor(),
"BlockBuilder_apply_extrinsic",
&tx.encode(),
@@ -127,6 +131,7 @@ mod tests {
backend,
sp_state_machine::disabled_changes_trie_state::<_, u64>(),
&mut overlay,
&mut offchain_overlay,
&executor(),
"BlockBuilder_finalize_block",
&[],
@@ -174,10 +179,13 @@ mod tests {
let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend");
let mut overlay = OverlayedChanges::default();
let mut offchain_overlay = OffchainOverlayedChanges::default();
let _ = StateMachine::new(
&backend,
sp_state_machine::disabled_changes_trie_state::<_, u64>(),
&mut overlay,
&mut offchain_overlay,
&executor(),
"Core_execute_block",
&b1data,
@@ -206,10 +214,13 @@ mod tests {
let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend");
let mut overlay = OverlayedChanges::default();
let mut offchain_overlay = OffchainOverlayedChanges::default();
let _ = StateMachine::new(
&backend,
sp_state_machine::disabled_changes_trie_state::<_, u64>(),
&mut overlay,
&mut offchain_overlay,
&executor(),
"Core_execute_block",
&b1data,
@@ -238,10 +249,13 @@ mod tests {
let runtime_code = backend_runtime_code.runtime_code().expect("Code is part of the backend");
let mut overlay = OverlayedChanges::default();
let mut offchain_overlay = OffchainOverlayedChanges::default();
let r = StateMachine::new(
&backend,
sp_state_machine::disabled_changes_trie_state::<_, u64>(),
&mut overlay,
&mut offchain_overlay,
&executor(),
"Core_execute_block",
&b1data,
+4 -2
View File
@@ -63,6 +63,7 @@
//! backend.clone(),
//! NativeExecutor::<LocalExecutor>::new(WasmExecutionMethod::Interpreted, None, 8),
//! sp_core::tasks::executor(),
//! Default::default(),
//! ),
//! // This parameter provides the storage for the chain genesis.
//! &<Storage>::default(),
@@ -70,6 +71,7 @@
//! Default::default(),
//! Default::default(),
//! None,
//! Default::default(),
//! );
//! ```
//!
@@ -99,8 +101,8 @@ pub use crate::{
client::{
new_with_backend,
new_in_mem,
BlockBackend, ImportNotifications, FinalityNotifications, BlockchainEvents, LockImportRun,
BlockImportNotification, Client, ClientInfo, ExecutionStrategies, FinalityNotification,
ImportNotifications, FinalityNotifications, BlockchainEvents, LockImportRun,
BlockImportNotification, Client, ClientConfig, ClientInfo, ExecutionStrategies, FinalityNotification,
LongestChain, BlockOf, ProvideUncles, BadBlocks, ForkBlocks, apply_aux,
},
leaves::LeafSet,
+4 -1
View File
@@ -21,7 +21,7 @@ use std::{
};
use codec::{Encode, Decode};
use sp_core::{convert_hash, NativeOrEncoded, traits::CodeExecutor};
use sp_core::{convert_hash, NativeOrEncoded, traits::CodeExecutor, offchain::storage::OffchainOverlayedChanges};
use sp_runtime::{
generic::BlockId, traits::{One, Block as BlockT, Header as HeaderT, HashFor},
};
@@ -108,6 +108,7 @@ impl<Block, B, Local> CallExecutor<Block> for
method: &str,
call_data: &[u8],
changes: &RefCell<OverlayedChanges>,
offchain_changes: &RefCell<OffchainOverlayedChanges>,
_: Option<&RefCell<StorageTransactionCache<Block, B::State>>>,
initialize_block: InitializeBlock<'a, Block>,
_manager: ExecutionManager<EM>,
@@ -134,6 +135,7 @@ impl<Block, B, Local> CallExecutor<Block> for
method,
call_data,
changes,
offchain_changes,
None,
initialize_block,
ExecutionManager::NativeWhenPossible,
@@ -338,6 +340,7 @@ mod tests {
_method: &str,
_call_data: &[u8],
_changes: &RefCell<OverlayedChanges>,
_offchain_changes: &RefCell<OffchainOverlayedChanges>,
_storage_transaction_cache: Option<&RefCell<
StorageTransactionCache<
Block,
+3 -2
View File
@@ -31,7 +31,7 @@ use sp_blockchain::Result as ClientResult;
use prometheus_endpoint::Registry;
use crate::call_executor::LocalCallExecutor;
use crate::client::Client;
use crate::client::{Client,ClientConfig};
use sc_client_api::{
light::Storage as BlockchainStorage, CloneableSpawn,
};
@@ -77,7 +77,7 @@ pub fn new_light<B, S, RA, E>(
S: BlockchainStorage<B> + 'static,
E: CodeExecutor + RuntimeInfo + Clone + 'static,
{
let local_executor = LocalCallExecutor::new(backend.clone(), code_executor, spawn_handle.clone());
let local_executor = LocalCallExecutor::new(backend.clone(), code_executor, spawn_handle.clone(), ClientConfig::default());
let executor = GenesisCallExecutor::new(backend.clone(), local_executor);
Client::new(
backend,
@@ -87,6 +87,7 @@ pub fn new_light<B, S, RA, E>(
Default::default(),
Default::default(),
prometheus_registry,
ClientConfig::default(),
)
}