// This file is part of Substrate.
// Copyright (C) 2019-2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program 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.
// This program 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 this program. If not, see .
//! Substrate offchain workers.
//!
//! The offchain workers is a special function of the runtime that
//! gets executed after block is imported. During execution
//! it's able to asynchronously submit extrinsics that will either
//! be propagated to other nodes or added to the next block
//! produced by the node as unsigned transactions.
//!
//! Offchain workers can be used for computation-heavy tasks
//! that are not feasible for execution during regular block processing.
//! It can either be tasks that no consensus is required for,
//! or some form of consensus over the data can be built on-chain
//! for instance via:
//! 1. Challenge period for incorrect computations
//! 2. Majority voting for results
//! 3. etc
#![warn(missing_docs)]
use std::{collections::HashSet, fmt, marker::PhantomData, sync::Arc};
use futures::{
future::{ready, Future},
prelude::*,
};
use log::{debug, warn};
use parking_lot::Mutex;
use sc_network::{ExHashT, NetworkService, NetworkStateInfo, PeerId};
use sp_api::{ApiExt, ProvideRuntimeApi};
use sp_core::{offchain, traits::SpawnNamed, ExecutionContext};
use sp_runtime::{
generic::BlockId,
traits::{self, Header},
};
use threadpool::ThreadPool;
mod api;
pub use api::Db as OffchainDb;
pub use sp_offchain::{OffchainWorkerApi, STORAGE_PREFIX};
/// NetworkProvider provides [`OffchainWorkers`] with all necessary hooks into the
/// underlying Substrate networking.
pub trait NetworkProvider: NetworkStateInfo {
/// Set the authorized peers.
fn set_authorized_peers(&self, peers: HashSet);
/// Set the authorized only flag.
fn set_authorized_only(&self, reserved_only: bool);
}
impl NetworkProvider for NetworkService
where
B: traits::Block + 'static,
H: ExHashT,
{
fn set_authorized_peers(&self, peers: HashSet) {
self.set_authorized_peers(peers)
}
fn set_authorized_only(&self, reserved_only: bool) {
self.set_authorized_only(reserved_only)
}
}
/// An offchain workers manager.
pub struct OffchainWorkers {
client: Arc,
_block: PhantomData,
thread_pool: Mutex,
shared_client: api::SharedClient,
}
impl OffchainWorkers {
/// Creates new `OffchainWorkers`.
pub fn new(client: Arc) -> Self {
let shared_client = api::SharedClient::new();
Self {
client,
_block: PhantomData,
thread_pool: Mutex::new(ThreadPool::with_name(
"offchain-worker".into(),
num_cpus::get(),
)),
shared_client,
}
}
}
impl fmt::Debug for OffchainWorkers {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("OffchainWorkers").finish()
}
}
impl OffchainWorkers
where
Block: traits::Block,
Client: ProvideRuntimeApi + Send + Sync + 'static,
Client::Api: OffchainWorkerApi,
{
/// Start the offchain workers after given block.
#[must_use]
pub fn on_block_imported(
&self,
header: &Block::Header,
network_provider: Arc,
is_validator: bool,
) -> impl Future