Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Forwardport: Validation: don't detect STDIN closing when running in p…
Browse files Browse the repository at this point in the history
…rocess (#1695) (#1703)

* Initial commit

Forked at: d04e449
Parent branch: origin/master

* Validation: don't detect STDIN closing when running in process  (#1695)
  • Loading branch information
cecton authored Sep 11, 2020
1 parent d04e449 commit 42eb3ce
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 124 deletions.
28 changes: 12 additions & 16 deletions node/core/candidate-validation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use polkadot_primitives::v1::{
};
use polkadot_parachain::wasm_executor::{
self, ValidationPool, ExecutionMode, ValidationError,
InvalidCandidate as WasmInvalidCandidate, ValidationExecutionMode,
InvalidCandidate as WasmInvalidCandidate,
};
use polkadot_parachain::primitives::{ValidationResult as WasmValidationResult, ValidationParams};

Expand Down Expand Up @@ -130,7 +130,7 @@ async fn run(
)
-> SubsystemResult<()>
{
let pool = ValidationPool::new(ValidationExecutionMode::ExternalProcessSelfHost);
let execution_mode = ExecutionMode::ExternalProcessSelfHost(ValidationPool::new());

loop {
match ctx.recv().await? {
Expand All @@ -145,7 +145,7 @@ async fn run(
) => {
let res = spawn_validate_from_chain_state(
&mut ctx,
Some(pool.clone()),
execution_mode.clone(),
descriptor,
pov,
spawn.clone(),
Expand All @@ -169,7 +169,7 @@ async fn run(
) => {
let res = spawn_validate_exhaustive(
&mut ctx,
Some(pool.clone()),
execution_mode.clone(),
persisted_validation_data,
transient_validation_data,
validation_code,
Expand Down Expand Up @@ -271,7 +271,7 @@ async fn check_assumption_validation_data(

async fn spawn_validate_from_chain_state(
ctx: &mut impl SubsystemContext<Message = CandidateValidationMessage>,
validation_pool: Option<ValidationPool>,
execution_mode: ExecutionMode,
descriptor: CandidateDescriptor,
pov: Arc<PoV>,
spawn: impl SpawnNamed + 'static,
Expand All @@ -288,7 +288,7 @@ async fn spawn_validate_from_chain_state(
AssumptionCheckOutcome::Matches(validation_data, validation_code) => {
return spawn_validate_exhaustive(
ctx,
validation_pool,
execution_mode,
validation_data.persisted,
Some(validation_data.transient),
validation_code,
Expand All @@ -309,7 +309,7 @@ async fn spawn_validate_from_chain_state(
AssumptionCheckOutcome::Matches(validation_data, validation_code) => {
return spawn_validate_exhaustive(
ctx,
validation_pool,
execution_mode,
validation_data.persisted,
Some(validation_data.transient),
validation_code,
Expand All @@ -330,7 +330,7 @@ async fn spawn_validate_from_chain_state(

async fn spawn_validate_exhaustive(
ctx: &mut impl SubsystemContext<Message = CandidateValidationMessage>,
validation_pool: Option<ValidationPool>,
execution_mode: ExecutionMode,
persisted_validation_data: PersistedValidationData,
transient_validation_data: Option<TransientValidationData>,
validation_code: ValidationCode,
Expand All @@ -341,7 +341,7 @@ async fn spawn_validate_exhaustive(
let (tx, rx) = oneshot::channel();
let fut = async move {
let res = validate_candidate_exhaustive::<RealValidationBackend, _>(
validation_pool,
execution_mode,
persisted_validation_data,
transient_validation_data,
validation_code,
Expand Down Expand Up @@ -422,22 +422,18 @@ trait ValidationBackend {
struct RealValidationBackend;

impl ValidationBackend for RealValidationBackend {
type Arg = Option<ValidationPool>;
type Arg = ExecutionMode;

fn validate<S: SpawnNamed + 'static>(
pool: Option<ValidationPool>,
execution_mode: ExecutionMode,
validation_code: &ValidationCode,
params: ValidationParams,
spawn: S,
) -> Result<WasmValidationResult, ValidationError> {
let execution_mode = pool.as_ref()
.map(ExecutionMode::Remote)
.unwrap_or(ExecutionMode::Local);

wasm_executor::validate_candidate(
&validation_code.0,
params,
execution_mode,
&execution_mode,
spawn,
)
}
Expand Down
48 changes: 33 additions & 15 deletions parachain/src/wasm_executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
//! Assuming the parameters are correct, this module provides a wrapper around
//! a WASM VM for re-execution of a parachain candidate.

use std::any::{TypeId, Any};
use std::{any::{TypeId, Any}, path::PathBuf};
use crate::primitives::{ValidationParams, ValidationResult};
use codec::{Decode, Encode};
use sp_core::{storage::{ChildInfo, TrackedStorageKey}, traits::{CallInWasm, SpawnNamed}};
use sp_externalities::Extensions;
use sp_wasm_interface::HostFunctions as _;

#[cfg(not(any(target_os = "android", target_os = "unknown")))]
pub use validation_host::{run_worker, ValidationPool, EXECUTION_TIMEOUT_SEC, ValidationExecutionMode};
pub use validation_host::{run_worker, ValidationPool, EXECUTION_TIMEOUT_SEC, WORKER_ARGS};

mod validation_host;

Expand Down Expand Up @@ -58,16 +58,29 @@ pub fn run_worker(_: &str) -> Result<(), String> {
Err("Cannot run validation worker on this platform".to_string())
}

/// WASM code execution mode.
///
/// > Note: When compiling for WASM, the `Remote` variants are not available.
pub enum ExecutionMode<'a> {
/// Execute in-process. The execution can not be interrupted or aborted.
Local,
/// Remote execution in a spawned process.
Remote(&'a ValidationPool),
/// The execution mode for the `ValidationPool`.
#[derive(Clone)]
#[cfg_attr(not(any(target_os = "android", target_os = "unknown")), derive(Debug))]
pub enum ExecutionMode {
/// The validation worker is ran in a thread inside the same process.
InProcess,
/// The validation worker is ran using the process' executable and the subcommand `validation-worker` is passed
/// following by the address of the shared memory.
ExternalProcessSelfHost(ValidationPool),
/// The validation worker is ran using the command provided and the argument provided. The address of the shared
/// memory is added at the end of the arguments.
ExternalProcessCustomHost {
/// Validation pool.
pool: ValidationPool,
/// Path to the validation worker. The file must exists and be executable.
binary: PathBuf,
/// List of arguments passed to the validation worker. The address of the shared memory will be automatically
/// added after the arguments.
args: Vec<String>,
},
}


#[derive(Debug, derive_more::Display, derive_more::From)]
/// Candidate validation error.
pub enum ValidationError {
Expand Down Expand Up @@ -132,19 +145,24 @@ impl std::error::Error for ValidationError {
pub fn validate_candidate(
validation_code: &[u8],
params: ValidationParams,
options: ExecutionMode<'_>,
execution_mode: &ExecutionMode,
spawner: impl SpawnNamed + 'static,
) -> Result<ValidationResult, ValidationError> {
match options {
ExecutionMode::Local => {
match execution_mode {
ExecutionMode::InProcess => {
validate_candidate_internal(validation_code, &params.encode(), spawner)
},
#[cfg(not(any(target_os = "android", target_os = "unknown")))]
ExecutionMode::Remote(pool) => {
ExecutionMode::ExternalProcessSelfHost(pool) => {
pool.validate_candidate(validation_code, params)
},
#[cfg(not(any(target_os = "android", target_os = "unknown")))]
ExecutionMode::ExternalProcessCustomHost { pool, binary, args } => {
let args: Vec<&str> = args.iter().map(|x| x.as_str()).collect();
pool.validate_candidate_custom(validation_code, params, binary, &args)
},
#[cfg(any(target_os = "android", target_os = "unknown"))]
ExecutionMode::Remote(_pool) =>
ExecutionMode::ExternalProcessSelfHost(_) | ExecutionMode::ExternalProcessCustomHost { .. } =>
Err(ValidationError::Internal(InternalError::System(
Box::<dyn std::error::Error + Send + Sync>::from(
"Remote validator not available".to_string()
Expand Down
Loading

0 comments on commit 42eb3ce

Please sign in to comment.