mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 10:31:03 +00:00
Rename ExecutionMode to IsolationStrategy (#1932)
* Rename ExecutionMode to IsolationStrategy Execution mode is too generic name and can imply a lot of different aspects of execution. The notion of isolation better describes the meant aspect. And while I am at it, I also renamed mode -> strategy cause it seems a bit more appropriate, although that is way more subjective. * Fix compilation in wasm_executor tests. * Add a comment to IsolationStrategy * Update comments on IsolationStrategy * Update node/core/candidate-validation/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Accomodate the point on interruption * Update parachain/src/wasm_executor/mod.rs Co-authored-by: Andronik Ordian <write@reusable.software> * Naming nits Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: Andronik Ordian <write@reusable.software>
This commit is contained in:
@@ -38,7 +38,9 @@ use polkadot_primitives::v1::{
|
|||||||
ValidationCode, PoV, CandidateDescriptor, PersistedValidationData,
|
ValidationCode, PoV, CandidateDescriptor, PersistedValidationData,
|
||||||
OccupiedCoreAssumption, Hash, ValidationOutputs,
|
OccupiedCoreAssumption, Hash, ValidationOutputs,
|
||||||
};
|
};
|
||||||
use polkadot_parachain::wasm_executor::{self, ExecutionMode, ValidationError, InvalidCandidate as WasmInvalidCandidate};
|
use polkadot_parachain::wasm_executor::{
|
||||||
|
self, IsolationStrategy, ValidationError, InvalidCandidate as WasmInvalidCandidate
|
||||||
|
};
|
||||||
use polkadot_parachain::primitives::{ValidationResult as WasmValidationResult, ValidationParams};
|
use polkadot_parachain::primitives::{ValidationResult as WasmValidationResult, ValidationParams};
|
||||||
|
|
||||||
use parity_scale_codec::Encode;
|
use parity_scale_codec::Encode;
|
||||||
@@ -55,13 +57,16 @@ const LOG_TARGET: &'static str = "candidate_validation";
|
|||||||
pub struct CandidateValidationSubsystem<S> {
|
pub struct CandidateValidationSubsystem<S> {
|
||||||
spawn: S,
|
spawn: S,
|
||||||
metrics: Metrics,
|
metrics: Metrics,
|
||||||
execution_mode: ExecutionMode,
|
isolation_strategy: IsolationStrategy,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> CandidateValidationSubsystem<S> {
|
impl<S> CandidateValidationSubsystem<S> {
|
||||||
/// Create a new `CandidateValidationSubsystem` with the given task spawner.
|
/// Create a new `CandidateValidationSubsystem` with the given task spawner and isolation
|
||||||
pub fn new(spawn: S, metrics: Metrics, execution_mode: ExecutionMode) -> Self {
|
/// strategy.
|
||||||
CandidateValidationSubsystem { spawn, metrics, execution_mode }
|
///
|
||||||
|
/// Check out [`IsolationStrategy`] to get more details.
|
||||||
|
pub fn new(spawn: S, metrics: Metrics, isolation_strategy: IsolationStrategy) -> Self {
|
||||||
|
CandidateValidationSubsystem { spawn, metrics, isolation_strategy }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +75,7 @@ impl<S, C> Subsystem<C> for CandidateValidationSubsystem<S> where
|
|||||||
S: SpawnNamed + Clone + 'static,
|
S: SpawnNamed + Clone + 'static,
|
||||||
{
|
{
|
||||||
fn start(self, ctx: C) -> SpawnedSubsystem {
|
fn start(self, ctx: C) -> SpawnedSubsystem {
|
||||||
let future = run(ctx, self.spawn, self.metrics, self.execution_mode)
|
let future = run(ctx, self.spawn, self.metrics, self.isolation_strategy)
|
||||||
.map_err(|e| SubsystemError::with_origin("candidate-validation", e))
|
.map_err(|e| SubsystemError::with_origin("candidate-validation", e))
|
||||||
.boxed();
|
.boxed();
|
||||||
SpawnedSubsystem {
|
SpawnedSubsystem {
|
||||||
@@ -84,7 +89,7 @@ async fn run(
|
|||||||
mut ctx: impl SubsystemContext<Message = CandidateValidationMessage>,
|
mut ctx: impl SubsystemContext<Message = CandidateValidationMessage>,
|
||||||
spawn: impl SpawnNamed + Clone + 'static,
|
spawn: impl SpawnNamed + Clone + 'static,
|
||||||
metrics: Metrics,
|
metrics: Metrics,
|
||||||
execution_mode: ExecutionMode,
|
isolation_strategy: IsolationStrategy,
|
||||||
) -> SubsystemResult<()> {
|
) -> SubsystemResult<()> {
|
||||||
loop {
|
loop {
|
||||||
match ctx.recv().await? {
|
match ctx.recv().await? {
|
||||||
@@ -99,7 +104,7 @@ async fn run(
|
|||||||
) => {
|
) => {
|
||||||
let res = spawn_validate_from_chain_state(
|
let res = spawn_validate_from_chain_state(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
execution_mode.clone(),
|
isolation_strategy.clone(),
|
||||||
descriptor,
|
descriptor,
|
||||||
pov,
|
pov,
|
||||||
spawn.clone(),
|
spawn.clone(),
|
||||||
@@ -122,7 +127,7 @@ async fn run(
|
|||||||
) => {
|
) => {
|
||||||
let res = spawn_validate_exhaustive(
|
let res = spawn_validate_exhaustive(
|
||||||
&mut ctx,
|
&mut ctx,
|
||||||
execution_mode.clone(),
|
isolation_strategy.clone(),
|
||||||
persisted_validation_data,
|
persisted_validation_data,
|
||||||
validation_code,
|
validation_code,
|
||||||
descriptor,
|
descriptor,
|
||||||
@@ -254,7 +259,7 @@ async fn find_assumed_validation_data(
|
|||||||
|
|
||||||
async fn spawn_validate_from_chain_state(
|
async fn spawn_validate_from_chain_state(
|
||||||
ctx: &mut impl SubsystemContext<Message = CandidateValidationMessage>,
|
ctx: &mut impl SubsystemContext<Message = CandidateValidationMessage>,
|
||||||
execution_mode: ExecutionMode,
|
isolation_strategy: IsolationStrategy,
|
||||||
descriptor: CandidateDescriptor,
|
descriptor: CandidateDescriptor,
|
||||||
pov: Arc<PoV>,
|
pov: Arc<PoV>,
|
||||||
spawn: impl SpawnNamed + 'static,
|
spawn: impl SpawnNamed + 'static,
|
||||||
@@ -277,7 +282,7 @@ async fn spawn_validate_from_chain_state(
|
|||||||
|
|
||||||
let validation_result = spawn_validate_exhaustive(
|
let validation_result = spawn_validate_exhaustive(
|
||||||
ctx,
|
ctx,
|
||||||
execution_mode,
|
isolation_strategy,
|
||||||
validation_data,
|
validation_data,
|
||||||
validation_code,
|
validation_code,
|
||||||
descriptor.clone(),
|
descriptor.clone(),
|
||||||
@@ -313,7 +318,7 @@ async fn spawn_validate_from_chain_state(
|
|||||||
|
|
||||||
async fn spawn_validate_exhaustive(
|
async fn spawn_validate_exhaustive(
|
||||||
ctx: &mut impl SubsystemContext<Message = CandidateValidationMessage>,
|
ctx: &mut impl SubsystemContext<Message = CandidateValidationMessage>,
|
||||||
execution_mode: ExecutionMode,
|
isolation_strategy: IsolationStrategy,
|
||||||
persisted_validation_data: PersistedValidationData,
|
persisted_validation_data: PersistedValidationData,
|
||||||
validation_code: ValidationCode,
|
validation_code: ValidationCode,
|
||||||
descriptor: CandidateDescriptor,
|
descriptor: CandidateDescriptor,
|
||||||
@@ -323,7 +328,7 @@ async fn spawn_validate_exhaustive(
|
|||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
let fut = async move {
|
let fut = async move {
|
||||||
let res = validate_candidate_exhaustive::<RealValidationBackend, _>(
|
let res = validate_candidate_exhaustive::<RealValidationBackend, _>(
|
||||||
execution_mode,
|
isolation_strategy,
|
||||||
persisted_validation_data,
|
persisted_validation_data,
|
||||||
validation_code,
|
validation_code,
|
||||||
descriptor,
|
descriptor,
|
||||||
@@ -379,10 +384,10 @@ trait ValidationBackend {
|
|||||||
struct RealValidationBackend;
|
struct RealValidationBackend;
|
||||||
|
|
||||||
impl ValidationBackend for RealValidationBackend {
|
impl ValidationBackend for RealValidationBackend {
|
||||||
type Arg = ExecutionMode;
|
type Arg = IsolationStrategy;
|
||||||
|
|
||||||
fn validate<S: SpawnNamed + 'static>(
|
fn validate<S: SpawnNamed + 'static>(
|
||||||
execution_mode: ExecutionMode,
|
isolation_strategy: IsolationStrategy,
|
||||||
validation_code: &ValidationCode,
|
validation_code: &ValidationCode,
|
||||||
params: ValidationParams,
|
params: ValidationParams,
|
||||||
spawn: S,
|
spawn: S,
|
||||||
@@ -390,7 +395,7 @@ impl ValidationBackend for RealValidationBackend {
|
|||||||
wasm_executor::validate_candidate(
|
wasm_executor::validate_candidate(
|
||||||
&validation_code.0,
|
&validation_code.0,
|
||||||
params,
|
params,
|
||||||
&execution_mode,
|
&isolation_strategy,
|
||||||
spawn,
|
spawn,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ use service::RpcHandlers;
|
|||||||
pub use self::client::{AbstractClient, Client, ClientHandle, ExecuteWithClient, RuntimeApiCollection};
|
pub use self::client::{AbstractClient, Client, ClientHandle, ExecuteWithClient, RuntimeApiCollection};
|
||||||
pub use chain_spec::{PolkadotChainSpec, KusamaChainSpec, WestendChainSpec, RococoChainSpec};
|
pub use chain_spec::{PolkadotChainSpec, KusamaChainSpec, WestendChainSpec, RococoChainSpec};
|
||||||
pub use consensus_common::{Proposal, SelectChain, BlockImport, RecordProof, block_validation::Chain};
|
pub use consensus_common::{Proposal, SelectChain, BlockImport, RecordProof, block_validation::Chain};
|
||||||
pub use polkadot_parachain::wasm_executor::ExecutionMode;
|
pub use polkadot_parachain::wasm_executor::IsolationStrategy;
|
||||||
pub use polkadot_primitives::v1::{Block, BlockId, CollatorId, Hash, Id as ParaId};
|
pub use polkadot_primitives::v1::{Block, BlockId, CollatorId, Hash, Id as ParaId};
|
||||||
pub use sc_client_api::{Backend, ExecutionStrategy, CallExecutor};
|
pub use sc_client_api::{Backend, ExecutionStrategy, CallExecutor};
|
||||||
pub use sc_consensus::LongestChain;
|
pub use sc_consensus::LongestChain;
|
||||||
@@ -296,7 +296,7 @@ fn real_overseer<Spawner, RuntimeClient>(
|
|||||||
registry: Option<&Registry>,
|
registry: Option<&Registry>,
|
||||||
spawner: Spawner,
|
spawner: Spawner,
|
||||||
_: IsCollator,
|
_: IsCollator,
|
||||||
_: ExecutionMode,
|
_: IsolationStrategy,
|
||||||
) -> Result<(Overseer<Spawner>, OverseerHandler), Error>
|
) -> Result<(Overseer<Spawner>, OverseerHandler), Error>
|
||||||
where
|
where
|
||||||
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
|
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
|
||||||
@@ -322,7 +322,7 @@ fn real_overseer<Spawner, RuntimeClient>(
|
|||||||
registry: Option<&Registry>,
|
registry: Option<&Registry>,
|
||||||
spawner: Spawner,
|
spawner: Spawner,
|
||||||
is_collator: IsCollator,
|
is_collator: IsCollator,
|
||||||
execution_mode: ExecutionMode,
|
isolation_strategy: IsolationStrategy,
|
||||||
) -> Result<(Overseer<Spawner>, OverseerHandler), Error>
|
) -> Result<(Overseer<Spawner>, OverseerHandler), Error>
|
||||||
where
|
where
|
||||||
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
|
RuntimeClient: 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
|
||||||
@@ -377,7 +377,7 @@ where
|
|||||||
candidate_validation: CandidateValidationSubsystem::new(
|
candidate_validation: CandidateValidationSubsystem::new(
|
||||||
spawner.clone(),
|
spawner.clone(),
|
||||||
Metrics::register(registry)?,
|
Metrics::register(registry)?,
|
||||||
execution_mode,
|
isolation_strategy,
|
||||||
),
|
),
|
||||||
chain_api: ChainApiSubsystem::new(
|
chain_api: ChainApiSubsystem::new(
|
||||||
runtime_client.clone(),
|
runtime_client.clone(),
|
||||||
@@ -479,7 +479,7 @@ pub fn new_full<RuntimeApi, Executor>(
|
|||||||
is_collator: IsCollator,
|
is_collator: IsCollator,
|
||||||
grandpa_pause: Option<(u32, u32)>,
|
grandpa_pause: Option<(u32, u32)>,
|
||||||
authority_discovery_config: Option<AuthorityWorkerConfig>,
|
authority_discovery_config: Option<AuthorityWorkerConfig>,
|
||||||
execution_mode: ExecutionMode,
|
isolation_strategy: IsolationStrategy,
|
||||||
) -> Result<NewFull<Arc<FullClient<RuntimeApi, Executor>>>, Error>
|
) -> Result<NewFull<Arc<FullClient<RuntimeApi, Executor>>>, Error>
|
||||||
where
|
where
|
||||||
RuntimeApi: ConstructRuntimeApi<Block, FullClient<RuntimeApi, Executor>> + Send + Sync + 'static,
|
RuntimeApi: ConstructRuntimeApi<Block, FullClient<RuntimeApi, Executor>> + Send + Sync + 'static,
|
||||||
@@ -615,7 +615,7 @@ pub fn new_full<RuntimeApi, Executor>(
|
|||||||
prometheus_registry.as_ref(),
|
prometheus_registry.as_ref(),
|
||||||
spawner,
|
spawner,
|
||||||
is_collator,
|
is_collator,
|
||||||
execution_mode,
|
isolation_strategy,
|
||||||
)?;
|
)?;
|
||||||
let overseer_handler_clone = overseer_handler.clone();
|
let overseer_handler_clone = overseer_handler.clone();
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ pub fn new_full(
|
|||||||
query_start_delay: Duration::from_secs(0),
|
query_start_delay: Duration::from_secs(0),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
polkadot_parachain::wasm_executor::ExecutionMode::InProcess,
|
polkadot_parachain::wasm_executor::IsolationStrategy::InProcess,
|
||||||
).map_err(Into::into)
|
).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,9 +37,40 @@ const MAX_RUNTIME_MEM: usize = 1024 * 1024 * 1024; // 1 GiB
|
|||||||
const MAX_CODE_MEM: usize = 16 * 1024 * 1024; // 16 MiB
|
const MAX_CODE_MEM: usize = 16 * 1024 * 1024; // 16 MiB
|
||||||
const MAX_VALIDATION_RESULT_HEADER_MEM: usize = MAX_CODE_MEM + 1024; // 16.001 MiB
|
const MAX_VALIDATION_RESULT_HEADER_MEM: usize = MAX_CODE_MEM + 1024; // 16.001 MiB
|
||||||
|
|
||||||
/// The execution mode for the `ValidationPool`.
|
/// The strategy we employ for isolating execution of wasm parachain validation function (PVF).
|
||||||
|
///
|
||||||
|
/// For a typical validator an external process is the default way to run PVF. The rationale is based
|
||||||
|
/// on the following observations:
|
||||||
|
///
|
||||||
|
/// (a) PVF is completely under control of parachain developers who may or may not be malicious.
|
||||||
|
/// (b) Collators are in charge of providing PoV who also may or may not be malicious.
|
||||||
|
/// (c) PVF is executed by a wasm engine based on optimizing compiler which is a very complex piece
|
||||||
|
/// of machinery.
|
||||||
|
///
|
||||||
|
/// (a) and (b) may lead to a situation where due to a combination of PVF and PoV the validation work
|
||||||
|
/// can stuck in an infinite loop, which can open up resource exhaustion or DoS attack vectors.
|
||||||
|
///
|
||||||
|
/// While some execution engines provide functionality to interrupt execution of wasm module from
|
||||||
|
/// another thread, there are also some caveats to that: there is no clean way to interrupt execution
|
||||||
|
/// if the control flow is in the host side and at the moment we haven't rigoriously vetted that all
|
||||||
|
/// host functions terminate or, at least, return in a short amount of time. Additionally, we want
|
||||||
|
/// some freedom on choosing wasm execution environment.
|
||||||
|
///
|
||||||
|
/// On top of that, execution in a separate process helps to minimize impact of (c) if exploited.
|
||||||
|
/// It's not only the risk of miscompilation, but it also includes risk of JIT-bombs, i.e. cases
|
||||||
|
/// of specially crafted code that take enourmous amounts of time and memory to compile.
|
||||||
|
///
|
||||||
|
/// At the same time, since PVF validates self-contained candidates, validation workers don't require
|
||||||
|
/// extensive communication with polkadot host, therefore there should be no observable performance penalty
|
||||||
|
/// coming from inter process communication.
|
||||||
|
///
|
||||||
|
/// All of the above should give a sense why isolation is crucial for a typical use-case.
|
||||||
|
///
|
||||||
|
/// However, in some cases, e.g. when running PVF validation on android (for whatever reason), we
|
||||||
|
/// cannot afford the luxury of process isolation and thus there is an option to run validation in
|
||||||
|
/// process. Also, running in process is convenient for testing.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum ExecutionMode {
|
pub enum IsolationStrategy {
|
||||||
/// The validation worker is ran in a thread inside the same process.
|
/// The validation worker is ran in a thread inside the same process.
|
||||||
InProcess,
|
InProcess,
|
||||||
/// The validation worker is ran using the process' executable and the subcommand `validation-worker` is passed
|
/// The validation worker is ran using the process' executable and the subcommand `validation-worker` is passed
|
||||||
@@ -60,7 +91,7 @@ pub enum ExecutionMode {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ExecutionMode {
|
impl Default for IsolationStrategy {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
#[cfg(not(any(target_os = "android", target_os = "unknown")))]
|
#[cfg(not(any(target_os = "android", target_os = "unknown")))]
|
||||||
{
|
{
|
||||||
@@ -136,19 +167,19 @@ pub enum InternalError {
|
|||||||
pub fn validate_candidate(
|
pub fn validate_candidate(
|
||||||
validation_code: &[u8],
|
validation_code: &[u8],
|
||||||
params: ValidationParams,
|
params: ValidationParams,
|
||||||
execution_mode: &ExecutionMode,
|
isolation_strategy: &IsolationStrategy,
|
||||||
spawner: impl SpawnNamed + 'static,
|
spawner: impl SpawnNamed + 'static,
|
||||||
) -> Result<ValidationResult, ValidationError> {
|
) -> Result<ValidationResult, ValidationError> {
|
||||||
match execution_mode {
|
match isolation_strategy {
|
||||||
ExecutionMode::InProcess => {
|
IsolationStrategy::InProcess => {
|
||||||
validate_candidate_internal(validation_code, ¶ms.encode(), spawner)
|
validate_candidate_internal(validation_code, ¶ms.encode(), spawner)
|
||||||
},
|
},
|
||||||
#[cfg(not(any(target_os = "android", target_os = "unknown")))]
|
#[cfg(not(any(target_os = "android", target_os = "unknown")))]
|
||||||
ExecutionMode::ExternalProcessSelfHost(pool) => {
|
IsolationStrategy::ExternalProcessSelfHost(pool) => {
|
||||||
pool.validate_candidate(validation_code, params)
|
pool.validate_candidate(validation_code, params)
|
||||||
},
|
},
|
||||||
#[cfg(not(any(target_os = "android", target_os = "unknown")))]
|
#[cfg(not(any(target_os = "android", target_os = "unknown")))]
|
||||||
ExecutionMode::ExternalProcessCustomHost { pool, binary, args } => {
|
IsolationStrategy::ExternalProcessCustomHost { pool, binary, args } => {
|
||||||
let args: Vec<&str> = args.iter().map(|x| x.as_str()).collect();
|
let args: Vec<&str> = args.iter().map(|x| x.as_str()).collect();
|
||||||
pool.validate_candidate_custom(validation_code, params, binary, &args)
|
pool.validate_candidate_custom(validation_code, params, binary, &args)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use futures::executor::block_on;
|
use futures::executor::block_on;
|
||||||
use polkadot_parachain::{primitives::ValidationParams, wasm_executor::ExecutionMode};
|
use polkadot_parachain::{primitives::ValidationParams, wasm_executor::IsolationStrategy};
|
||||||
use polkadot_primitives::v1::{ValidationData, PersistedValidationData};
|
use polkadot_primitives::v1::{ValidationData, PersistedValidationData};
|
||||||
use codec::Decode;
|
use codec::Decode;
|
||||||
|
|
||||||
@@ -201,7 +201,7 @@ mod tests {
|
|||||||
hrmp_mqc_heads: Vec::new(),
|
hrmp_mqc_heads: Vec::new(),
|
||||||
dmq_mqc_head: Default::default(),
|
dmq_mqc_head: Default::default(),
|
||||||
},
|
},
|
||||||
&ExecutionMode::InProcess,
|
&IsolationStrategy::InProcess,
|
||||||
sp_core::testing::TaskExecutor::new(),
|
sp_core::testing::TaskExecutor::new(),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -25,13 +25,13 @@ use parachain::{
|
|||||||
HeadData as GenericHeadData,
|
HeadData as GenericHeadData,
|
||||||
ValidationParams,
|
ValidationParams,
|
||||||
},
|
},
|
||||||
wasm_executor::{ValidationPool, ExecutionMode}
|
wasm_executor::{ValidationPool, IsolationStrategy}
|
||||||
};
|
};
|
||||||
use codec::{Decode, Encode};
|
use codec::{Decode, Encode};
|
||||||
use adder::{HeadData, BlockData, hash_state};
|
use adder::{HeadData, BlockData, hash_state};
|
||||||
|
|
||||||
fn execution_mode() -> ExecutionMode {
|
fn isolation_strategy() -> IsolationStrategy {
|
||||||
ExecutionMode::ExternalProcessCustomHost {
|
IsolationStrategy::ExternalProcessCustomHost {
|
||||||
pool: ValidationPool::new(),
|
pool: ValidationPool::new(),
|
||||||
binary: std::env::current_exe().unwrap(),
|
binary: std::env::current_exe().unwrap(),
|
||||||
args: WORKER_ARGS_TEST.iter().map(|x| x.to_string()).collect(),
|
args: WORKER_ARGS_TEST.iter().map(|x| x.to_string()).collect(),
|
||||||
@@ -40,17 +40,17 @@ fn execution_mode() -> ExecutionMode {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn execute_good_on_parent_with_inprocess_validation() {
|
fn execute_good_on_parent_with_inprocess_validation() {
|
||||||
let execution_mode = ExecutionMode::InProcess;
|
let isolation_strategy = IsolationStrategy::InProcess;
|
||||||
execute_good_on_parent(execution_mode);
|
execute_good_on_parent(isolation_strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn execute_good_on_parent_with_external_process_validation() {
|
pub fn execute_good_on_parent_with_external_process_validation() {
|
||||||
let execution_mode = execution_mode();
|
let isolation_strategy = isolation_strategy();
|
||||||
execute_good_on_parent(execution_mode);
|
execute_good_on_parent(isolation_strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_good_on_parent(execution_mode: ExecutionMode) {
|
fn execute_good_on_parent(isolation_strategy: IsolationStrategy) {
|
||||||
let parent_head = HeadData {
|
let parent_head = HeadData {
|
||||||
number: 0,
|
number: 0,
|
||||||
parent_hash: [0; 32],
|
parent_hash: [0; 32],
|
||||||
@@ -71,7 +71,7 @@ fn execute_good_on_parent(execution_mode: ExecutionMode) {
|
|||||||
hrmp_mqc_heads: Vec::new(),
|
hrmp_mqc_heads: Vec::new(),
|
||||||
dmq_mqc_head: Default::default(),
|
dmq_mqc_head: Default::default(),
|
||||||
},
|
},
|
||||||
&execution_mode,
|
&isolation_strategy,
|
||||||
sp_core::testing::TaskExecutor::new(),
|
sp_core::testing::TaskExecutor::new(),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ fn execute_good_chain_on_parent() {
|
|||||||
let mut number = 0;
|
let mut number = 0;
|
||||||
let mut parent_hash = [0; 32];
|
let mut parent_hash = [0; 32];
|
||||||
let mut last_state = 0;
|
let mut last_state = 0;
|
||||||
let execution_mode = execution_mode();
|
let isolation_strategy = isolation_strategy();
|
||||||
|
|
||||||
for add in 0..10 {
|
for add in 0..10 {
|
||||||
let parent_head = HeadData {
|
let parent_head = HeadData {
|
||||||
@@ -110,7 +110,7 @@ fn execute_good_chain_on_parent() {
|
|||||||
hrmp_mqc_heads: Vec::new(),
|
hrmp_mqc_heads: Vec::new(),
|
||||||
dmq_mqc_head: Default::default(),
|
dmq_mqc_head: Default::default(),
|
||||||
},
|
},
|
||||||
&execution_mode,
|
&isolation_strategy,
|
||||||
sp_core::testing::TaskExecutor::new(),
|
sp_core::testing::TaskExecutor::new(),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ fn execute_good_chain_on_parent() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn execute_bad_on_parent() {
|
fn execute_bad_on_parent() {
|
||||||
let execution_mode = execution_mode();
|
let isolation_strategy = isolation_strategy();
|
||||||
|
|
||||||
let parent_head = HeadData {
|
let parent_head = HeadData {
|
||||||
number: 0,
|
number: 0,
|
||||||
@@ -150,7 +150,7 @@ fn execute_bad_on_parent() {
|
|||||||
hrmp_mqc_heads: Vec::new(),
|
hrmp_mqc_heads: Vec::new(),
|
||||||
dmq_mqc_head: Default::default(),
|
dmq_mqc_head: Default::default(),
|
||||||
},
|
},
|
||||||
&execution_mode,
|
&isolation_strategy,
|
||||||
sp_core::testing::TaskExecutor::new(),
|
sp_core::testing::TaskExecutor::new(),
|
||||||
).unwrap_err();
|
).unwrap_err();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ const WORKER_ARGS_TEST: &[&'static str] = &["--nocapture", "validation_worker"];
|
|||||||
use crate::adder;
|
use crate::adder;
|
||||||
use parachain::{
|
use parachain::{
|
||||||
primitives::{BlockData, ValidationParams},
|
primitives::{BlockData, ValidationParams},
|
||||||
wasm_executor::{ValidationError, InvalidCandidate, EXECUTION_TIMEOUT_SEC, ExecutionMode, ValidationPool},
|
wasm_executor::{ValidationError, InvalidCandidate, EXECUTION_TIMEOUT_SEC, IsolationStrategy, ValidationPool},
|
||||||
};
|
};
|
||||||
|
|
||||||
fn execution_mode() -> ExecutionMode {
|
fn isolation_strategy() -> IsolationStrategy {
|
||||||
ExecutionMode::ExternalProcessCustomHost {
|
IsolationStrategy::ExternalProcessCustomHost {
|
||||||
pool: ValidationPool::new(),
|
pool: ValidationPool::new(),
|
||||||
binary: std::env::current_exe().unwrap(),
|
binary: std::env::current_exe().unwrap(),
|
||||||
args: WORKER_ARGS_TEST.iter().map(|x| x.to_string()).collect(),
|
args: WORKER_ARGS_TEST.iter().map(|x| x.to_string()).collect(),
|
||||||
@@ -34,7 +34,7 @@ fn execution_mode() -> ExecutionMode {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn terminates_on_timeout() {
|
fn terminates_on_timeout() {
|
||||||
let execution_mode = execution_mode();
|
let isolation_strategy = isolation_strategy();
|
||||||
|
|
||||||
let result = parachain::wasm_executor::validate_candidate(
|
let result = parachain::wasm_executor::validate_candidate(
|
||||||
halt::wasm_binary_unwrap(),
|
halt::wasm_binary_unwrap(),
|
||||||
@@ -45,7 +45,7 @@ fn terminates_on_timeout() {
|
|||||||
hrmp_mqc_heads: Vec::new(),
|
hrmp_mqc_heads: Vec::new(),
|
||||||
dmq_mqc_head: Default::default(),
|
dmq_mqc_head: Default::default(),
|
||||||
},
|
},
|
||||||
&execution_mode,
|
&isolation_strategy,
|
||||||
sp_core::testing::TaskExecutor::new(),
|
sp_core::testing::TaskExecutor::new(),
|
||||||
);
|
);
|
||||||
match result {
|
match result {
|
||||||
@@ -59,11 +59,10 @@ fn terminates_on_timeout() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parallel_execution() {
|
fn parallel_execution() {
|
||||||
let execution_mode = execution_mode();
|
let isolation_strategy = isolation_strategy();
|
||||||
|
let isolation_strategy_clone = isolation_strategy.clone();
|
||||||
|
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
|
||||||
let execution_mode2 = execution_mode.clone();
|
|
||||||
let thread = std::thread::spawn(move ||
|
let thread = std::thread::spawn(move ||
|
||||||
parachain::wasm_executor::validate_candidate(
|
parachain::wasm_executor::validate_candidate(
|
||||||
halt::wasm_binary_unwrap(),
|
halt::wasm_binary_unwrap(),
|
||||||
@@ -74,7 +73,7 @@ fn parallel_execution() {
|
|||||||
hrmp_mqc_heads: Vec::new(),
|
hrmp_mqc_heads: Vec::new(),
|
||||||
dmq_mqc_head: Default::default(),
|
dmq_mqc_head: Default::default(),
|
||||||
},
|
},
|
||||||
&execution_mode,
|
&isolation_strategy,
|
||||||
sp_core::testing::TaskExecutor::new(),
|
sp_core::testing::TaskExecutor::new(),
|
||||||
).ok());
|
).ok());
|
||||||
let _ = parachain::wasm_executor::validate_candidate(
|
let _ = parachain::wasm_executor::validate_candidate(
|
||||||
@@ -86,7 +85,7 @@ fn parallel_execution() {
|
|||||||
hrmp_mqc_heads: Vec::new(),
|
hrmp_mqc_heads: Vec::new(),
|
||||||
dmq_mqc_head: Default::default(),
|
dmq_mqc_head: Default::default(),
|
||||||
},
|
},
|
||||||
&execution_mode2,
|
&isolation_strategy_clone,
|
||||||
sp_core::testing::TaskExecutor::new(),
|
sp_core::testing::TaskExecutor::new(),
|
||||||
);
|
);
|
||||||
thread.join().unwrap();
|
thread.join().unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user