// This file is part of Substrate.
// Copyright (C) 2019-2022 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::{fmt, marker::PhantomData, sync::Arc};
use futures::{
future::{ready, Future},
prelude::*,
};
use parking_lot::Mutex;
use sc_network_common::service::{NetworkPeers, NetworkStateInfo};
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};
const LOG_TARGET: &str = "offchain-worker";
/// NetworkProvider provides [`OffchainWorkers`] with all necessary hooks into the
/// underlying Substrate networking.
pub trait NetworkProvider: NetworkStateInfo + NetworkPeers {}
impl NetworkProvider for T where T: NetworkStateInfo + NetworkPeers {}
/// Options for [`OffchainWorkers`]
pub struct OffchainWorkerOptions {
/// Enable http requests from offchain workers?
///
/// If not enabled, any http request will panic.
pub enable_http_requests: bool,
}
/// An offchain workers manager.
pub struct OffchainWorkers {
client: Arc,
_block: PhantomData,
thread_pool: Mutex,
shared_http_client: api::SharedClient,
enable_http: bool,
}
impl OffchainWorkers {
/// Creates new [`OffchainWorkers`].
pub fn new(client: Arc) -> Self {
Self::new_with_options(client, OffchainWorkerOptions { enable_http_requests: true })
}
/// Creates new [`OffchainWorkers`] using the given `options`.
pub fn new_with_options(client: Arc, options: OffchainWorkerOptions) -> Self {
Self {
client,
_block: PhantomData,
thread_pool: Mutex::new(ThreadPool::with_name(
"offchain-worker".into(),
num_cpus::get(),
)),
shared_http_client: api::SharedClient::new(),
enable_http: options.enable_http_requests,
}
}
}
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