Refactors the offchain worker api (#3150)

* Update offchain primitives.

* Update offchain worker.

* Update im-online.

* Update service.

* Update node and node-template.

* Update runtime version.

* Fix build.

* Fix offchain worker tests.

* Generalize authority_pubkey.

* Add test.

* Update lib.rs
This commit is contained in:
David Craven
2019-07-22 11:20:57 +02:00
committed by Gavin Wood
parent 2edeef5825
commit a3d19baea3
17 changed files with 509 additions and 327 deletions
+17 -3
View File
@@ -30,7 +30,7 @@ use runtime_primitives::{
BuildStorage, traits::{Block as BlockT, Header as HeaderT, ProvideRuntimeApi}, generic::BlockId
};
use crate::config::Configuration;
use primitives::{Blake2Hasher, H256};
use primitives::{Blake2Hasher, H256, Pair};
use rpc::{self, apis::system::SystemInfo};
use futures::{prelude::*, future::Executor, sync::mpsc};
@@ -128,6 +128,16 @@ pub type ComponentOffchainStorage<C> = <
/// Block type for `Components`
pub type ComponentBlock<C> = <<C as Components>::Factory as ServiceFactory>::Block;
/// ConsensusPair type for `Components`
pub type ComponentConsensusPair<C> = <<C as Components>::Factory as ServiceFactory>::ConsensusPair;
/// FinalityPair type for `Components`
pub type ComponentFinalityPair<C> = <<C as Components>::Factory as ServiceFactory>::FinalityPair;
/// AuthorityKeyProvider type for `Components`
pub type ComponentAuthorityKeyProvider<C> =
AuthorityKeyProvider<ComponentBlock<C>, ComponentConsensusPair<C>, ComponentFinalityPair<C>>;
/// Extrinsic hash type for `Components`
pub type ComponentExHash<C> = <<C as Components>::TransactionPoolApi as txpool::ChainApi>::Hash;
@@ -231,7 +241,7 @@ pub trait OffchainWorker<C: Components> {
offchain: &offchain::OffchainWorkers<
ComponentClient<C>,
ComponentOffchainStorage<C>,
AuthorityKeyProvider,
ComponentAuthorityKeyProvider<C>,
ComponentBlock<C>
>,
pool: &Arc<TransactionPool<C::TransactionPoolApi>>,
@@ -248,7 +258,7 @@ impl<C: Components> OffchainWorker<Self> for C where
offchain: &offchain::OffchainWorkers<
ComponentClient<C>,
ComponentOffchainStorage<C>,
AuthorityKeyProvider,
ComponentAuthorityKeyProvider<C>,
ComponentBlock<C>
>,
pool: &Arc<TransactionPool<C::TransactionPoolApi>>,
@@ -283,6 +293,10 @@ pub type TaskExecutor = Arc<dyn Executor<Box<dyn Future<Item = (), Error = ()> +
pub trait ServiceFactory: 'static + Sized {
/// Block type.
type Block: BlockT<Hash=H256>;
/// Consensus crypto type.
type ConsensusPair: Pair;
/// Finality crypto type.
type FinalityPair: Pair;
/// The type that implements the runtime API.
type RuntimeApi: Send + Sync;
/// Network protocol extensions.
+69 -17
View File
@@ -26,6 +26,7 @@ pub mod chain_ops;
pub mod error;
use std::io;
use std::marker::PhantomData;
use std::net::SocketAddr;
use std::collections::HashMap;
use std::time::Duration;
@@ -42,7 +43,7 @@ use log::{info, warn, debug, error};
use parity_codec::{Encode, Decode};
use primitives::{Pair, ed25519, crypto};
use runtime_primitives::generic::BlockId;
use runtime_primitives::traits::{Header, NumberFor, SaturatedConversion};
use runtime_primitives::traits::{Header, NumberFor, SaturatedConversion, Zero};
use substrate_executor::NativeExecutor;
use sysinfo::{get_current_pid, ProcessExt, System, SystemExt};
use tel::{telemetry, SUBSTRATE_INFO};
@@ -55,12 +56,14 @@ pub use transaction_pool::txpool::{
};
pub use client::FinalityNotifications;
pub use components::{ServiceFactory, FullBackend, FullExecutor, LightBackend,
pub use components::{
ServiceFactory, FullBackend, FullExecutor, LightBackend, ComponentAuthorityKeyProvider,
LightExecutor, Components, PoolApi, ComponentClient, ComponentOffchainStorage,
ComponentBlock, FullClient, LightClient, FullComponents, LightComponents,
CodeExecutor, NetworkService, FactoryChainSpec, FactoryBlock,
FactoryFullConfiguration, RuntimeGenesis, FactoryGenesis,
ComponentExHash, ComponentExtrinsic, FactoryExtrinsic
ComponentExHash, ComponentExtrinsic, FactoryExtrinsic,
ComponentConsensusPair, ComponentFinalityPair,
};
use components::{StartRPC, MaintainTransactionPool, OffchainWorker};
#[doc(hidden)]
@@ -82,7 +85,7 @@ pub struct Service<Components: components::Components> {
NetworkStatus<ComponentBlock<Components>>, NetworkState
)>>>>,
transaction_pool: Arc<TransactionPool<Components::TransactionPoolApi>>,
keystore: AuthorityKeyProvider,
keystore: ComponentAuthorityKeyProvider<Components>,
exit: ::exit_future::Exit,
signal: Option<Signal>,
/// Sender for futures that must be spawned as background tasks.
@@ -102,7 +105,7 @@ pub struct Service<Components: components::Components> {
_offchain_workers: Option<Arc<offchain::OffchainWorkers<
ComponentClient<Components>,
ComponentOffchainStorage<Components>,
AuthorityKeyProvider,
ComponentAuthorityKeyProvider<Components>,
ComponentBlock<Components>>
>>,
}
@@ -264,6 +267,7 @@ impl<Components: components::Components> Service<Components> {
let network_status_sinks = Arc::new(Mutex::new(Vec::new()));
let keystore_authority_key = AuthorityKeyProvider {
_marker: PhantomData,
roles: config.roles,
password: config.password.clone(),
keystore: keystore.map(Arc::new),
@@ -498,10 +502,17 @@ impl<Components: components::Components> Service<Components> {
}
/// give the authority key, if we are an authority and have a key
pub fn authority_key<TPair: Pair>(&self) -> Option<TPair> {
pub fn authority_key(&self) -> Option<ComponentConsensusPair<Components>> {
use offchain::AuthorityKeyProvider;
self.keystore.authority_key()
self.keystore.authority_key(&BlockId::Number(Zero::zero()))
}
/// give the authority key, if we are an authority and have a key
pub fn fg_authority_key(&self) -> Option<ComponentFinalityPair<Components>> {
use offchain::AuthorityKeyProvider;
self.keystore.fg_authority_key(&BlockId::Number(Zero::zero()))
}
/// return a shared instance of Telemetry (if enabled)
@@ -531,7 +542,8 @@ impl<Components: components::Components> Service<Components> {
/// If the request subscribes you to events, the `Sender` in the `RpcSession` object is used to
/// send back spontaneous events.
pub fn rpc_query(&self, mem: &RpcSession, request: &str)
-> impl Future<Item = Option<String>, Error = ()> {
-> impl Future<Item = Option<String>, Error = ()>
{
self.rpc_handlers.handle_request(request, mem.metadata.clone())
}
@@ -733,7 +745,7 @@ impl<Components> Drop for Service<Components> where Components: components::Comp
fn start_rpc_servers<F: ServiceFactory, H: FnMut() -> rpc::RpcHandler>(
config: &FactoryFullConfiguration<F>,
mut gen_handler: H
) -> Result<Box<std::any::Any + Send + Sync>, error::Error> {
) -> Result<Box<dyn std::any::Any + Send + Sync>, error::Error> {
fn maybe_start_server<T, F>(address: Option<SocketAddr>, mut start: F) -> Result<Option<T>, io::Error>
where F: FnMut(&SocketAddr) -> Result<T, io::Error>,
{
@@ -876,16 +888,27 @@ impl<C: Components> network::TransactionPool<ComponentExHash<C>, ComponentBlock<
}
}
/// A provider of current authority key.
#[derive(Clone)]
pub struct AuthorityKeyProvider {
/// A provider of current authority key.
pub struct AuthorityKeyProvider<Block, ConsensusPair, FinalityPair> {
_marker: PhantomData<(Block, ConsensusPair, FinalityPair)>,
roles: Roles,
keystore: Option<Arc<Keystore>>,
password: crypto::Protected<String>,
}
impl offchain::AuthorityKeyProvider for AuthorityKeyProvider {
fn authority_key<TPair: Pair>(&self) -> Option<TPair> {
impl<Block, ConsensusPair, FinalityPair>
offchain::AuthorityKeyProvider<Block>
for AuthorityKeyProvider<Block, ConsensusPair, FinalityPair>
where
Block: runtime_primitives::traits::Block,
ConsensusPair: Pair,
FinalityPair: Pair,
{
type ConsensusPair = ConsensusPair;
type FinalityPair = FinalityPair;
fn authority_key(&self, _at: &BlockId<Block>) -> Option<Self::ConsensusPair> {
if self.roles != Roles::AUTHORITY {
return None
}
@@ -896,10 +919,33 @@ impl offchain::AuthorityKeyProvider for AuthorityKeyProvider {
};
let loaded_key = keystore
.contents()
.map(|keys| keys.get(0)
.map(|k| keystore.load(k, self.password.as_ref()))
);
.contents()
.map(|keys| keys.get(0)
.map(|k| keystore.load(k, self.password.as_ref()))
);
if let Ok(Some(Ok(key))) = loaded_key {
Some(key)
} else {
None
}
}
fn fg_authority_key(&self, _at: &BlockId<Block>) -> Option<Self::FinalityPair> {
if self.roles != Roles::AUTHORITY {
return None
}
let keystore = match self.keystore {
Some(ref keystore) => keystore,
None => return None
};
let loaded_key = keystore
.contents()
.map(|keys| keys.get(0)
.map(|k| keystore.load(k, self.password.as_ref()))
);
if let Ok(Some(Ok(key))) = loaded_key {
Some(key)
@@ -957,6 +1003,8 @@ impl offchain::AuthorityKeyProvider for AuthorityKeyProvider {
/// struct Factory {
/// // Declare the block type
/// Block = Block,
/// ConsensusPair = primitives::ed25519::Pair,
/// FinalityPair = primitives::ed25519::Pair,
/// RuntimeApi = RuntimeApi,
/// // Declare the network protocol and give an initializer.
/// NetworkProtocol = NodeProtocol { |config| Ok(NodeProtocol::new()) },
@@ -1000,6 +1048,8 @@ macro_rules! construct_service_factory {
$(#[$attr:meta])*
struct $name:ident {
Block = $block:ty,
ConsensusPair = $consensus_pair:ty,
FinalityPair = $finality_pair:ty,
RuntimeApi = $runtime_api:ty,
NetworkProtocol = $protocol:ty { $( $protocol_init:tt )* },
RuntimeDispatch = $dispatch:ty,
@@ -1025,6 +1075,8 @@ macro_rules! construct_service_factory {
#[allow(unused_variables)]
impl $crate::ServiceFactory for $name {
type Block = $block;
type ConsensusPair = $consensus_pair;
type FinalityPair = $finality_pair;
type RuntimeApi = $runtime_api;
type NetworkProtocol = $protocol;
type RuntimeDispatch = $dispatch;