Initial: Offchain Workers (#1942)

* Refactor state-machine stuff.

* Fix tests.

* WiP

* WiP2

* Service support for offchain workers.

* Service support for offchain workers.

* Testing offchain worker.

* Initial version working.

* Pass side effects in call.

* Pass OffchainExt in context.

* Submit extrinsics to the pool.

* Support inherents.

* Insert to inherents pool.

* Inserting to the pool asynchronously.

* Add test to offchain worker.

* Implement convenience syntax for modules.

* Dispatching offchain worker through executive.

* Fix offchain test.

* Remove offchain worker from timestamp.

* Update Cargo.lock.

* Address review comments.

* Use latest patch version for futures.

* Add CLI parameter for offchain worker.

* Fix compilation.

* Fix test.

* Fix extrinsics format for tests.

* Fix RPC test.

* Bump spec version.

* Fix executive.

* Fix support macro.

* Address grumbles.

* Bump runtime
This commit is contained in:
Tomasz Drwięga
2019-03-25 23:22:11 +01:00
committed by Gav Wood
parent 3ee0e69463
commit e2f5e40876
58 changed files with 1158 additions and 178 deletions
+51 -17
View File
@@ -17,7 +17,7 @@
//! Substrate service. Starts a thread that spins up the network, client, and extrinsic pool.
//! Manages communication between them.
#![warn(unused_extern_crates)]
#![warn(missing_docs)]
mod components;
mod error;
@@ -28,20 +28,18 @@ pub mod chain_ops;
use std::io;
use std::net::SocketAddr;
use std::collections::HashMap;
#[doc(hidden)]
pub use std::{ops::Deref, result::Result, sync::Arc};
use log::{info, warn, debug};
use futures::prelude::*;
use keystore::Store as Keystore;
use client::BlockchainEvents;
use exit_future::Signal;
use futures::prelude::*;
use inherents::pool::InherentsPool;
use keystore::Store as Keystore;
use log::{info, warn, debug};
use parity_codec::{Encode, Decode};
use primitives::Pair;
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{Header, As};
use exit_future::Signal;
#[doc(hidden)]
pub use tokio::runtime::TaskExecutor;
use substrate_executor::NativeExecutor;
use parity_codec::{Encode, Decode};
use tel::{telemetry, SUBSTRATE_INFO};
pub use self::error::{ErrorKind, Error};
@@ -59,9 +57,13 @@ pub use components::{ServiceFactory, FullBackend, FullExecutor, LightBackend,
FactoryFullConfiguration, RuntimeGenesis, FactoryGenesis,
ComponentExHash, ComponentExtrinsic, FactoryExtrinsic
};
use components::{StartRPC, MaintainTransactionPool};
use components::{StartRPC, MaintainTransactionPool, OffchainWorker};
#[doc(hidden)]
pub use std::{ops::Deref, result::Result, sync::Arc};
#[doc(hidden)]
pub use network::OnDemand;
#[doc(hidden)]
pub use tokio::runtime::TaskExecutor;
const DEFAULT_PROTOCOL_ID: &str = "sup";
@@ -70,6 +72,7 @@ pub struct Service<Components: components::Components> {
client: Arc<ComponentClient<Components>>,
network: Option<Arc<components::NetworkService<Components::Factory>>>,
transaction_pool: Arc<TransactionPool<Components::TransactionPoolApi>>,
inherents_pool: Arc<InherentsPool<ComponentExtrinsic<Components>>>,
keystore: Keystore,
exit: ::exit_future::Exit,
signal: Option<Signal>,
@@ -77,6 +80,7 @@ pub struct Service<Components: components::Components> {
pub config: FactoryFullConfiguration<Components::Factory>,
_rpc: Box<::std::any::Any + Send + Sync>,
_telemetry: Option<Arc<tel::Telemetry>>,
_offchain_workers: Option<Arc<offchain::OffchainWorkers<ComponentClient<Components>, ComponentBlock<Components>>>>,
}
/// Creates bare client without any networking.
@@ -96,9 +100,7 @@ impl<Components: components::Components> Service<Components> {
pub fn new(
mut config: FactoryFullConfiguration<Components::Factory>,
task_executor: TaskExecutor,
)
-> Result<Self, error::Error>
{
) -> Result<Self, error::Error> {
let (signal, exit) = ::exit_future::signal();
// Create client
@@ -169,24 +171,48 @@ impl<Components: components::Components> Service<Components> {
)?;
on_demand.map(|on_demand| on_demand.set_network_sender(network_chan));
let inherents_pool = Arc::new(InherentsPool::default());
let offchain_workers = if config.offchain_worker {
Some(Arc::new(offchain::OffchainWorkers::new(
client.clone(),
inherents_pool.clone(),
task_executor.clone(),
)))
} else {
None
};
{
// block notifications
let network = Arc::downgrade(&network);
let txpool = Arc::downgrade(&transaction_pool);
let wclient = Arc::downgrade(&client);
let offchain = offchain_workers.as_ref().map(Arc::downgrade);
let events = client.import_notification_stream()
.for_each(move |notification| {
let number = *notification.header.number();
if let Some(network) = network.upgrade() {
network.on_block_imported(notification.hash, notification.header);
}
if let (Some(txpool), Some(client)) = (txpool.upgrade(), wclient.upgrade()) {
Components::TransactionPool::on_block_imported(
Components::RuntimeServices::maintain_transaction_pool(
&BlockId::hash(notification.hash),
&*client,
&*txpool,
).map_err(|e| warn!("Pool error processing new block: {:?}", e))?;
}
if let (Some(txpool), Some(offchain)) = (txpool.upgrade(), offchain.as_ref().and_then(|o| o.upgrade())) {
Components::RuntimeServices::offchain_workers(
&number,
&offchain,
&txpool,
).map_err(|e| warn!("Offchain workers error processing new block: {:?}", e))?;
}
Ok(())
})
.select(exit.clone())
@@ -264,7 +290,7 @@ impl<Components: components::Components> Service<Components> {
impl_version: config.impl_version.into(),
properties: config.chain_spec.properties(),
};
let rpc = Components::RPC::start_rpc(
let rpc = Components::RuntimeServices::start_rpc(
client.clone(), network.clone(), has_bootnodes, system_info, config.rpc_http,
config.rpc_ws, task_executor.clone(), transaction_pool.clone(),
)?;
@@ -299,12 +325,14 @@ impl<Components: components::Components> Service<Components> {
client,
network: Some(network),
transaction_pool,
inherents_pool,
signal: Some(signal),
keystore,
config,
exit,
_rpc: Box::new(rpc),
_telemetry: telemetry,
_offchain_workers: offchain_workers,
})
}
@@ -321,6 +349,7 @@ impl<Components: components::Components> Service<Components> {
}
}
/// return a shared instance of Telemtry (if enabled)
pub fn telemetry(&self) -> Option<Arc<tel::Telemetry>> {
self._telemetry.as_ref().map(|t| t.clone())
}
@@ -337,11 +366,16 @@ impl<Components> Service<Components> where Components: components::Components {
self.network.as_ref().expect("self.network always Some").clone()
}
/// Get shared extrinsic pool instance.
/// Get shared transaction pool instance.
pub fn transaction_pool(&self) -> Arc<TransactionPool<Components::TransactionPoolApi>> {
self.transaction_pool.clone()
}
/// Get shared inherents pool instance.
pub fn inherents_pool(&self) -> Arc<InherentsPool<ComponentExtrinsic<Components>>> {
self.inherents_pool.clone()
}
/// Get shared keystore.
pub fn keystore(&self) -> &Keystore {
&self.keystore