mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 15:11:03 +00:00
Adds --no-validator CLI flag (#3348)
* Implement `is_validator` for offchain-workers * Introduce `--no-validator` flag * Don't run babe/grandpa/im-online when `--no-validator` is given * Fixes compilation * Bump spec version * Improve error handling in executor * Add missing extern function * Revert making error public * Remove `--no-validator` CLI
This commit is contained in:
@@ -436,6 +436,8 @@ where
|
||||
),
|
||||
};
|
||||
|
||||
let is_dev = cli.shared_params.dev;
|
||||
|
||||
let role = if cli.light {
|
||||
service::Roles::LIGHT
|
||||
} else {
|
||||
@@ -462,8 +464,6 @@ where
|
||||
config.roles = role;
|
||||
config.disable_grandpa = cli.no_grandpa;
|
||||
|
||||
let is_dev = cli.shared_params.dev;
|
||||
|
||||
let client_id = config.client_id();
|
||||
fill_network_configuration(
|
||||
cli.network_config,
|
||||
|
||||
@@ -38,8 +38,8 @@ pub enum Error {
|
||||
#[display(fmt="Method not found: '{}'", _0)]
|
||||
MethodNotFound(String),
|
||||
/// Code is invalid (expected single byte)
|
||||
#[display(fmt="Invalid Code")]
|
||||
InvalidCode,
|
||||
#[display(fmt="Invalid Code: {}", _0)]
|
||||
InvalidCode(String),
|
||||
/// Could not get runtime version.
|
||||
#[display(fmt="On-chain runtime does not specify version")]
|
||||
VersionInvalid,
|
||||
|
||||
@@ -22,7 +22,7 @@ use runtime_version::{NativeVersion, RuntimeVersion};
|
||||
use codec::{Decode, Encode};
|
||||
use crate::RuntimeInfo;
|
||||
use primitives::{Blake2Hasher, NativeOrEncoded};
|
||||
use log::trace;
|
||||
use log::{trace, warn};
|
||||
|
||||
use crate::RuntimesCache;
|
||||
|
||||
@@ -107,8 +107,14 @@ impl<D: NativeExecutionDispatch> RuntimeInfo for NativeExecutor<D> {
|
||||
) -> Option<RuntimeVersion> {
|
||||
RUNTIMES_CACHE.with(|cache| {
|
||||
let cache = &mut cache.borrow_mut();
|
||||
cache.fetch_runtime(&self.fallback, ext, self.default_heap_pages)
|
||||
.ok()?.version().clone()
|
||||
|
||||
match cache.fetch_runtime(&self.fallback, ext, self.default_heap_pages) {
|
||||
Ok(runtime) => runtime.version(),
|
||||
Err(e) => {
|
||||
warn!(target: "executor", "Failed to fetch runtime: {:?}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -876,6 +876,13 @@ impl_function_executor!(this: FunctionExecutor<'e, E>,
|
||||
|
||||
Ok(0)
|
||||
},
|
||||
ext_is_validator() -> u32 => {
|
||||
Ok(if runtime_io::is_validator() {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
})
|
||||
},
|
||||
ext_submit_transaction(msg_data: *const u8, len: u32) -> u32 => {
|
||||
let extrinsic = this.memory.get(msg_data, len as usize)
|
||||
.map_err(|_| "OOB while ext_submit_transaction: wasm")?;
|
||||
|
||||
@@ -248,12 +248,12 @@ impl RuntimesCache {
|
||||
) -> Result<Rc<CachedRuntime>, Error> {
|
||||
let code_hash = ext
|
||||
.original_storage_hash(well_known_keys::CODE)
|
||||
.ok_or(Error::InvalidCode)?;
|
||||
.ok_or(Error::InvalidCode("`CODE` not found in storage.".into()))?;
|
||||
|
||||
// This is direct result from fighting with borrowck.
|
||||
let handle_result =
|
||||
|cached_result: &Result<Rc<CachedRuntime>, CacheError>| match *cached_result {
|
||||
Err(_) => Err(Error::InvalidCode),
|
||||
Err(ref e) => Err(Error::InvalidCode(format!("{:?}", e))),
|
||||
Ok(ref cached_runtime) => Ok(Rc::clone(cached_runtime)),
|
||||
};
|
||||
|
||||
|
||||
@@ -47,11 +47,15 @@ pub(crate) struct Api<Storage, Block: traits::Block> {
|
||||
db: Storage,
|
||||
network_state: Arc<dyn NetworkStateInfo + Send + Sync>,
|
||||
_at: BlockId<Block>,
|
||||
/// Is this node a potential validator?
|
||||
is_validator: bool,
|
||||
}
|
||||
|
||||
fn unavailable_yet<R: Default>(name: &str) -> R {
|
||||
error!("The {:?} API is not available for offchain workers yet. Follow \
|
||||
https://github.com/paritytech/substrate/issues/1458 for details", name);
|
||||
error!(
|
||||
"The {:?} API is not available for offchain workers yet. Follow \
|
||||
https://github.com/paritytech/substrate/issues/1458 for details", name
|
||||
);
|
||||
Default::default()
|
||||
}
|
||||
|
||||
@@ -63,6 +67,10 @@ where
|
||||
Storage: OffchainStorage,
|
||||
Block: traits::Block,
|
||||
{
|
||||
fn is_validator(&self) -> bool {
|
||||
self.is_validator
|
||||
}
|
||||
|
||||
fn submit_transaction(&mut self, ext: Vec<u8>) -> Result<(), ()> {
|
||||
self.sender
|
||||
.unbounded_send(ExtMessage::SubmitExtrinsic(ext))
|
||||
@@ -277,6 +285,7 @@ impl<A: ChainApi> AsyncApi<A> {
|
||||
db: S,
|
||||
at: BlockId<A::Block>,
|
||||
network_state: Arc<dyn NetworkStateInfo + Send + Sync>,
|
||||
is_validator: bool,
|
||||
) -> (Api<S, A::Block>, AsyncApi<A>) {
|
||||
let (sender, rx) = mpsc::unbounded();
|
||||
|
||||
@@ -285,6 +294,7 @@ impl<A: ChainApi> AsyncApi<A> {
|
||||
db,
|
||||
network_state,
|
||||
_at: at,
|
||||
is_validator,
|
||||
};
|
||||
|
||||
let async_api = AsyncApi {
|
||||
@@ -362,6 +372,7 @@ mod tests {
|
||||
db,
|
||||
BlockId::Number(Zero::zero()),
|
||||
mock,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -98,9 +98,8 @@ impl<Client, Storage, Block> OffchainWorkers<
|
||||
number: &<Block::Header as traits::Header>::Number,
|
||||
pool: &Arc<Pool<A>>,
|
||||
network_state: Arc<dyn NetworkStateInfo + Send + Sync>,
|
||||
) -> impl Future<Output = ()> where
|
||||
A: ChainApi<Block=Block> + 'static,
|
||||
{
|
||||
is_validator: bool,
|
||||
) -> impl Future<Output = ()> where A: ChainApi<Block=Block> + 'static {
|
||||
let runtime = self.client.runtime_api();
|
||||
let at = BlockId::number(*number);
|
||||
let has_api = runtime.has_api::<dyn OffchainWorkerApi<Block>>(&at);
|
||||
@@ -112,6 +111,7 @@ impl<Client, Storage, Block> OffchainWorkers<
|
||||
self.db.clone(),
|
||||
at.clone(),
|
||||
network_state.clone(),
|
||||
is_validator,
|
||||
);
|
||||
debug!("Spawning offchain workers at {:?}", at);
|
||||
let number = *number;
|
||||
@@ -177,7 +177,7 @@ mod tests {
|
||||
|
||||
// when
|
||||
let offchain = OffchainWorkers::new(client, db);
|
||||
futures::executor::block_on(offchain.on_block_imported(&0u64, &pool, network_state));
|
||||
futures::executor::block_on(offchain.on_block_imported(&0u64, &pool, network_state, false));
|
||||
|
||||
// then
|
||||
assert_eq!(pool.status().ready, 1);
|
||||
|
||||
@@ -134,6 +134,10 @@ impl TestOffchainExt {
|
||||
}
|
||||
|
||||
impl offchain::Externalities for TestOffchainExt {
|
||||
fn is_validator(&self) -> bool {
|
||||
unimplemented!("not needed in tests so far")
|
||||
}
|
||||
|
||||
fn submit_transaction(&mut self, _ex: Vec<u8>) -> Result<(), ()> {
|
||||
unimplemented!("not needed in tests so far")
|
||||
}
|
||||
|
||||
@@ -232,6 +232,11 @@ impl Timestamp {
|
||||
|
||||
/// An extended externalities for offchain workers.
|
||||
pub trait Externalities {
|
||||
/// Returns if the local node is a potential validator.
|
||||
///
|
||||
/// Even if this function returns `true`, it does not mean that any keys are configured
|
||||
/// and that the validator is registered in the chain.
|
||||
fn is_validator(&self) -> bool;
|
||||
/// Submit transaction.
|
||||
///
|
||||
/// The transaction will end up in the pool and be propagated to others.
|
||||
@@ -349,6 +354,10 @@ pub trait Externalities {
|
||||
|
||||
}
|
||||
impl<T: Externalities + ?Sized> Externalities for Box<T> {
|
||||
fn is_validator(&self) -> bool {
|
||||
(& **self).is_validator()
|
||||
}
|
||||
|
||||
fn submit_transaction(&mut self, ex: Vec<u8>) -> Result<(), ()> {
|
||||
(&mut **self).submit_transaction(ex)
|
||||
}
|
||||
|
||||
@@ -268,6 +268,7 @@ pub trait OffchainWorker<C: Components> {
|
||||
>,
|
||||
pool: &Arc<TransactionPool<C::TransactionPoolApi>>,
|
||||
network_state: &Arc<dyn NetworkStateInfo + Send + Sync>,
|
||||
is_validator: bool,
|
||||
) -> error::Result<Box<dyn Future<Item = (), Error = ()> + Send>>;
|
||||
}
|
||||
|
||||
@@ -284,8 +285,9 @@ impl<C: Components> OffchainWorker<Self> for C where
|
||||
>,
|
||||
pool: &Arc<TransactionPool<C::TransactionPoolApi>>,
|
||||
network_state: &Arc<dyn NetworkStateInfo + Send + Sync>,
|
||||
is_validator: bool,
|
||||
) -> error::Result<Box<dyn Future<Item = (), Error = ()> + Send>> {
|
||||
let future = offchain.on_block_imported(number, pool, network_state.clone())
|
||||
let future = offchain.on_block_imported(number, pool, network_state.clone(), is_validator)
|
||||
.map(|()| Ok(()));
|
||||
Ok(Box::new(Compat::new(future)))
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ impl<Components: components::Components> Service<Components> {
|
||||
pub fn new(
|
||||
mut config: FactoryFullConfiguration<Components::Factory>,
|
||||
) -> Result<Self, error::Error> {
|
||||
let (signal, exit) = ::exit_future::signal();
|
||||
let (signal, exit) = exit_future::signal();
|
||||
|
||||
// List of asynchronous tasks to spawn. We collect them, then spawn them all at once.
|
||||
let (to_spawn_tx, to_spawn_rx) =
|
||||
@@ -250,6 +250,7 @@ impl<Components: components::Components> Service<Components> {
|
||||
let offchain = offchain_workers.as_ref().map(Arc::downgrade);
|
||||
let to_spawn_tx_ = to_spawn_tx.clone();
|
||||
let network_state_info: Arc<dyn NetworkStateInfo + Send + Sync> = network.clone();
|
||||
let is_validator = config.roles.is_authority();
|
||||
|
||||
let events = client.import_notification_stream()
|
||||
.map(|v| Ok::<_, ()>(v)).compat()
|
||||
@@ -270,6 +271,7 @@ impl<Components: components::Components> Service<Components> {
|
||||
&offchain,
|
||||
&txpool,
|
||||
&network_state_info,
|
||||
is_validator,
|
||||
).map_err(|e| warn!("Offchain workers error processing new block: {:?}", e))?;
|
||||
let _ = to_spawn_tx_.unbounded_send(future);
|
||||
}
|
||||
|
||||
@@ -273,6 +273,11 @@ export_api! {
|
||||
|
||||
export_api! {
|
||||
pub(crate) trait OffchainApi {
|
||||
/// Returns if the local node is a potential validator.
|
||||
///
|
||||
/// Even if this function returns `true`, it does not mean that any keys are configured
|
||||
/// and that the validator is registered in the chain.
|
||||
fn is_validator() -> bool;
|
||||
/// Submit transaction to the pool.
|
||||
///
|
||||
/// The transaction will end up in the pool.
|
||||
|
||||
@@ -336,6 +336,12 @@ fn with_offchain<R>(f: impl FnOnce(&mut dyn offchain::Externalities) -> R, msg:
|
||||
}
|
||||
|
||||
impl OffchainApi for () {
|
||||
fn is_validator() -> bool {
|
||||
with_offchain(|ext| {
|
||||
ext.is_validator()
|
||||
}, "is_validator can be called only in the offchain worker context")
|
||||
}
|
||||
|
||||
fn submit_transaction<T: codec::Encode>(data: &T) -> Result<(), ()> {
|
||||
with_offchain(|ext| {
|
||||
ext.submit_transaction(codec::Encode::encode(data))
|
||||
|
||||
@@ -432,6 +432,12 @@ pub mod ext {
|
||||
// Offchain-worker Context
|
||||
//================================
|
||||
|
||||
/// Returns if the local node is a potential validator.
|
||||
///
|
||||
/// - `1` == `true`
|
||||
/// - `0` == `false`
|
||||
fn ext_is_validator() -> u32;
|
||||
|
||||
/// Submit transaction.
|
||||
///
|
||||
/// # Returns
|
||||
@@ -964,6 +970,10 @@ impl CryptoApi for () {
|
||||
}
|
||||
|
||||
impl OffchainApi for () {
|
||||
fn is_validator() -> bool {
|
||||
unsafe { ext_is_validator.get()() == 1 }
|
||||
}
|
||||
|
||||
fn submit_transaction<T: codec::Encode>(data: &T) -> Result<(), ()> {
|
||||
let encoded_data = codec::Encode::encode(data);
|
||||
let ret = unsafe {
|
||||
|
||||
@@ -263,6 +263,10 @@ impl NeverOffchainExt {
|
||||
}
|
||||
|
||||
impl offchain::Externalities for NeverOffchainExt {
|
||||
fn is_validator(&self) -> bool {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn submit_transaction(&mut self, _extrinsic: Vec<u8>) -> Result<(), ()> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
@@ -138,15 +138,15 @@ construct_service_factory! {
|
||||
let select = babe.select(service.on_exit()).then(|_| Ok(()));
|
||||
service.spawn_task(Box::new(select));
|
||||
|
||||
let config = grandpa::Config {
|
||||
// FIXME #1578 make this available through chainspec
|
||||
gossip_duration: Duration::from_millis(333),
|
||||
justification_period: 4096,
|
||||
name: Some(service.config().name.clone()),
|
||||
keystore: Some(service.keystore()),
|
||||
};
|
||||
|
||||
if !service.config().disable_grandpa {
|
||||
let config = grandpa::Config {
|
||||
// FIXME #1578 make this available through chainspec
|
||||
gossip_duration: Duration::from_millis(333),
|
||||
justification_period: 4096,
|
||||
name: Some(service.config().name.clone()),
|
||||
keystore: Some(service.keystore()),
|
||||
};
|
||||
|
||||
if service.config().roles.is_authority() {
|
||||
let telemetry_on_connect = TelemetryOnConnect {
|
||||
telemetry_connection_sinks: service.telemetry_on_connect_stream(),
|
||||
|
||||
@@ -80,8 +80,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
// and set impl_version to equal spec_version. If only runtime
|
||||
// implementation changes and behavior does not, then leave spec_version as
|
||||
// is and increment impl_version.
|
||||
spec_version: 136,
|
||||
impl_version: 136,
|
||||
spec_version: 137,
|
||||
impl_version: 137,
|
||||
apis: RUNTIME_API_VERSIONS,
|
||||
};
|
||||
|
||||
|
||||
@@ -219,7 +219,10 @@ decl_module! {
|
||||
|
||||
// Runs after every block.
|
||||
fn offchain_worker(now: T::BlockNumber) {
|
||||
Self::offchain(now);
|
||||
// Only send messages if we are a potential validator.
|
||||
if sr_io::is_validator() {
|
||||
Self::offchain(now);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user