PVF: Add test instructions (#2058)

This commit is contained in:
Marcin S
2023-11-28 14:23:25 +01:00
committed by GitHub
parent cd8741c8b5
commit dbd8d20b25
18 changed files with 146 additions and 60 deletions
+47
View File
@@ -0,0 +1,47 @@
# PVF Host
This is the PVF host, responsible for responding to requests from Candidate
Validation and spawning worker tasks to fulfill those requests.
See also:
- for more information: [the Implementer's Guide][impl-guide]
- for an explanation of terminology: [the Glossary][glossary]
## Running basic tests
Running `cargo test` in the `pvf/` directory will run unit and integration
tests.
**Note:** some tests run only under Linux, amd64, and/or with the
`ci-only-tests` feature enabled.
See the general [Testing][testing] instructions for more information on
**running tests** and **observing logs**.
## Running a test-network with zombienet
Since this crate is consensus-critical, for major changes it is highly
recommended to run a test-network. See the "Behavior tests" section of the
[Testing][testing] docs for full instructions.
To run the PVF-specific zombienet test:
```sh
RUST_LOG=parachain::pvf=trace zombienet --provider=native spawn zombienet_tests/functional/0001-parachains-pvf.toml
```
## Testing on Linux
Some of the PVF functionality, especially related to security, is Linux-only,
and some is amd64-only. If you touch anything security-related, make sure to
test on Linux amd64! If you're on a Mac, you can either run a VM or you can hire
a VPS and use the open-source tool [EternalTerminal][et] to connect to it.[^et]
[^et]: Unlike ssh, ET preserves your session across disconnects, and unlike
another popular persistent shell, mosh, it allows scrollback.
[impl-guide]: https://paritytech.github.io/polkadot-sdk/book/pvf-prechecking.html#summary
[glossary]: https://paritytech.github.io/polkadot-sdk/book/glossary.html
[testing]: https://github.com/paritytech/polkadot-sdk/blob/master/polkadot/doc/testing.md
[et]: https://github.com/MisterTea/EternalTerminal
@@ -175,11 +175,9 @@ pub fn params_to_wasmtime_semantics(par: &ExecutorParams) -> Semantics {
/// Runs the prevalidation on the given code. Returns a [`RuntimeBlob`] if it succeeds.
pub fn prevalidate(code: &[u8]) -> Result<RuntimeBlob, sc_executor_common::error::WasmError> {
// Construct the runtime blob and do some basic checks for consistency.
let blob = RuntimeBlob::new(code)?;
// It's assumed this function will take care of any prevalidation logic
// that needs to be done.
//
// Do nothing for now.
// In the future this function should take care of any further prevalidation logic.
Ok(blob)
}
+1 -1
View File
@@ -18,7 +18,7 @@
pub mod error;
pub mod execute;
pub mod executor_intf;
pub mod executor_interface;
pub mod prepare;
pub mod pvf;
pub mod worker;
@@ -17,7 +17,7 @@
//! Contains the logic for executing PVFs. Used by the polkadot-execute-worker binary.
pub use polkadot_node_core_pvf_common::{
executor_intf::execute_artifact, worker_dir, SecurityStatus,
executor_interface::execute_artifact, worker_dir, SecurityStatus,
};
// NOTE: Initializing logging in e.g. tests will not have an effect in the workers, as they are
@@ -236,7 +236,7 @@ fn validate_using_artifact(
let descriptor_bytes = match unsafe {
// SAFETY: this should be safe since the compiled artifact passed here comes from the
// file created by the prepare workers. These files are obtained by calling
// [`executor_intf::prepare`].
// [`executor_interface::prepare`].
execute_artifact(compiled_artifact_blob, executor_params, params)
} {
Err(err) => return JobResponse::format_invalid("execute", &err),
@@ -16,7 +16,7 @@
use criterion::{criterion_group, criterion_main, Criterion, SamplingMode};
use polkadot_node_core_pvf_common::{
executor_intf::{prepare, prevalidate},
executor_interface::{prepare, prevalidate},
prepare::PrepareJobKind,
pvf::PvfPrepData,
};
@@ -18,7 +18,7 @@
mod memory_stats;
use polkadot_node_core_pvf_common::executor_intf::{prepare, prevalidate};
use polkadot_node_core_pvf_common::executor_interface::{prepare, prevalidate};
// NOTE: Initializing logging in e.g. tests will not have an effect in the workers, as they are
// separate spawned processes. Run with e.g. `RUST_LOG=parachain::pvf-prepare-worker=trace`.
@@ -41,7 +41,7 @@ use os_pipe::{self, PipeReader, PipeWriter};
use parity_scale_codec::{Decode, Encode};
use polkadot_node_core_pvf_common::{
error::{PrepareError, PrepareWorkerResult},
executor_intf::create_runtime_from_artifact_bytes,
executor_interface::create_runtime_from_artifact_bytes,
framed_recv_blocking, framed_send_blocking,
prepare::{MemoryStats, PrepareJobKind, PrepareStats, PrepareWorkerSuccess},
pvf::PvfPrepData,
+1 -1
View File
@@ -21,6 +21,6 @@
//! `polkadot_node_core_pvf_worker::execute_worker_entrypoint`.
mod queue;
mod worker_intf;
mod worker_interface;
pub use queue::{start, PendingExecutionRequest, ToQueue};
+4 -4
View File
@@ -16,12 +16,12 @@
//! A queue that handles requests for PVF execution.
use super::worker_intf::Outcome;
use super::worker_interface::Outcome;
use crate::{
artifacts::{ArtifactId, ArtifactPathId},
host::ResultSender,
metrics::Metrics,
worker_intf::{IdleWorker, WorkerHandle},
worker_interface::{IdleWorker, WorkerHandle},
InvalidCandidate, PossiblyInvalidError, ValidationError, LOG_TARGET,
};
use futures::{
@@ -448,7 +448,7 @@ async fn spawn_worker_task(
use futures_timer::Delay;
loop {
match super::worker_intf::spawn(
match super::worker_interface::spawn(
&program_path,
&cache_path,
job.executor_params.clone(),
@@ -500,7 +500,7 @@ fn assign(queue: &mut Queue, worker: Worker, job: ExecuteJob) {
queue.mux.push(
async move {
let _timer = execution_timer;
let outcome = super::worker_intf::start_work(
let outcome = super::worker_interface::start_work(
idle,
job.artifact.clone(),
job.exec_timeout,
@@ -18,7 +18,7 @@
use crate::{
artifacts::ArtifactPathId,
worker_intf::{
worker_interface::{
clear_worker_dir_path, framed_recv, framed_send, spawn_with_program_path, IdleWorker,
SpawnErr, WorkerDir, WorkerHandle, JOB_TIMEOUT_WALL_CLOCK_FACTOR,
},
+2 -2
View File
@@ -98,7 +98,7 @@ mod metrics;
mod prepare;
mod priority;
mod security;
mod worker_intf;
mod worker_interface;
#[cfg(feature = "test-utils")]
pub mod testing;
@@ -107,7 +107,7 @@ pub use error::{InvalidCandidate, PossiblyInvalidError, ValidationError};
pub use host::{start, Config, ValidationHost, EXECUTE_BINARY_NAME, PREPARE_BINARY_NAME};
pub use metrics::Metrics;
pub use priority::Priority;
pub use worker_intf::{framed_recv, framed_send, JOB_TIMEOUT_WALL_CLOCK_FACTOR};
pub use worker_interface::{framed_recv, framed_send, JOB_TIMEOUT_WALL_CLOCK_FACTOR};
// Re-export some common types.
pub use polkadot_node_core_pvf_common::{
+1 -1
View File
@@ -24,7 +24,7 @@
mod pool;
mod queue;
mod worker_intf;
mod worker_interface;
pub use pool::start as start_pool;
pub use queue::{start as start_queue, FromQueue, ToQueue};
+4 -4
View File
@@ -14,10 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use super::worker_intf::{self, Outcome};
use super::worker_interface::{self, Outcome};
use crate::{
metrics::Metrics,
worker_intf::{IdleWorker, WorkerHandle},
worker_interface::{IdleWorker, WorkerHandle},
LOG_TARGET,
};
use always_assert::never;
@@ -278,7 +278,7 @@ async fn spawn_worker_task(
use futures_timer::Delay;
loop {
match worker_intf::spawn(
match worker_interface::spawn(
&program_path,
&cache_path,
spawn_timeout,
@@ -306,7 +306,7 @@ async fn start_work_task<Timer>(
cache_path: PathBuf,
_preparation_timer: Option<Timer>,
) -> PoolEvent {
let outcome = worker_intf::start_work(&metrics, idle, pvf, cache_path).await;
let outcome = worker_interface::start_work(&metrics, idle, pvf, cache_path).await;
PoolEvent::StartWork(worker, outcome)
}
@@ -19,7 +19,7 @@
use crate::{
artifacts::ArtifactId,
metrics::Metrics,
worker_intf::{
worker_interface::{
clear_worker_dir_path, framed_recv, framed_send, spawn_with_program_path, IdleWorker,
SpawnErr, WorkerDir, WorkerHandle, JOB_TIMEOUT_WALL_CLOCK_FACTOR,
},
+2 -2
View File
@@ -18,7 +18,7 @@
pub use crate::{
host::{EXECUTE_BINARY_NAME, PREPARE_BINARY_NAME},
worker_intf::{spawn_with_program_path, SpawnErr},
worker_interface::{spawn_with_program_path, SpawnErr},
};
use crate::get_worker_version;
@@ -36,7 +36,7 @@ pub fn validate_candidate(
code: &[u8],
params: &[u8],
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
use polkadot_node_core_pvf_common::executor_intf::{prepare, prevalidate};
use polkadot_node_core_pvf_common::executor_interface::{prepare, prevalidate};
use polkadot_node_core_pvf_execute_worker::execute_artifact;
let code = sp_maybe_compressed_blob::decompress(code, 10 * 1024 * 1024)
-9
View File
@@ -1,9 +0,0 @@
# PVF host integration tests
## Testing
Before running these tests, make sure the worker binaries are built first. This can be done with:
```sh
cargo build --bin polkadot-execute-worker --bin polkadot-prepare-worker
```