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

Commit 8bb8e07

Browse files
author
Andronik
committed
Merge branch 'ao-past-session-slashing-runtime' into ao-past-session-slashing-client
* ao-past-session-slashing-runtime: XCM: Tools for uniquely referencing messages (#7234) Companion: Substrate#13869 (#7119) Companion for Substrate#14214 (#7283) Fix flaky test and error reporting (#7282) impl guide: Update Collator Generation (#7250) Add staking-miner bin (#7273) metrics: tests: Fix flaky runtime_can_publish_metrics (#7279) [companion] Fix request-response protocols backpressure mechanism (#7276) PVF: instantiate runtime from bytes (#7270)
2 parents cfe4be4 + f2bcd9b commit 8bb8e07

File tree

73 files changed

+1886
-1037
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+1886
-1037
lines changed

Cargo.lock

Lines changed: 338 additions & 328 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

node/collation-generation/src/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@
1515
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
1616

1717
//! The collation generation subsystem is the interface between polkadot and the collators.
18+
//!
19+
//! # Protocol
20+
//!
21+
//! On every `ActiveLeavesUpdate`:
22+
//!
23+
//! * If there is no collation generation config, ignore.
24+
//! * Otherwise, for each `activated` head in the update:
25+
//! * Determine if the para is scheduled on any core by fetching the `availability_cores` Runtime API.
26+
//! * Use the Runtime API subsystem to fetch the full validation data.
27+
//! * Invoke the `collator`, and use its outputs to produce a [`CandidateReceipt`], signed with the configuration's `key`.
28+
//! * Dispatch a [`CollatorProtocolMessage::DistributeCollation`](receipt, pov)`.
1829
1930
#![deny(missing_docs)]
2031

node/core/dispute-coordinator/src/initialized.rs

Lines changed: 50 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -217,62 +217,61 @@ impl Initialized {
217217
gum::trace!(target: LOG_TARGET, "Waiting for message");
218218
let mut overlay_db = OverlayedBackend::new(backend);
219219
let default_confirm = Box::new(|| Ok(()));
220-
let confirm_write = match MuxedMessage::receive(ctx, &mut self.participation_receiver)
221-
.await?
222-
{
223-
MuxedMessage::Participation(msg) => {
224-
gum::trace!(target: LOG_TARGET, "MuxedMessage::Participation");
225-
let ParticipationStatement {
226-
session,
227-
candidate_hash,
228-
candidate_receipt,
229-
outcome,
230-
} = self.participation.get_participation_result(ctx, msg).await?;
231-
if let Some(valid) = outcome.validity() {
232-
gum::trace!(
233-
target: LOG_TARGET,
234-
?session,
235-
?candidate_hash,
236-
?valid,
237-
"Issuing local statement based on participation outcome."
238-
);
239-
self.issue_local_statement(
240-
ctx,
241-
&mut overlay_db,
220+
let confirm_write =
221+
match MuxedMessage::receive(ctx, &mut self.participation_receiver).await? {
222+
MuxedMessage::Participation(msg) => {
223+
gum::trace!(target: LOG_TARGET, "MuxedMessage::Participation");
224+
let ParticipationStatement {
225+
session,
242226
candidate_hash,
243227
candidate_receipt,
244-
session,
245-
valid,
246-
clock.now(),
247-
)
248-
.await?;
249-
} else {
250-
gum::warn!(target: LOG_TARGET, ?outcome, "Dispute participation failed");
251-
}
252-
default_confirm
253-
},
254-
MuxedMessage::Subsystem(msg) => match msg {
255-
FromOrchestra::Signal(OverseerSignal::Conclude) => return Ok(()),
256-
FromOrchestra::Signal(OverseerSignal::ActiveLeaves(update)) => {
257-
gum::trace!(target: LOG_TARGET, "OverseerSignal::ActiveLeaves");
258-
self.process_active_leaves_update(
259-
ctx,
260-
&mut overlay_db,
261-
update,
262-
clock.now(),
263-
)
264-
.await?;
228+
outcome,
229+
} = self.participation.get_participation_result(ctx, msg).await?;
230+
if let Some(valid) = outcome.validity() {
231+
gum::trace!(
232+
target: LOG_TARGET,
233+
?session,
234+
?candidate_hash,
235+
?valid,
236+
"Issuing local statement based on participation outcome."
237+
);
238+
self.issue_local_statement(
239+
ctx,
240+
&mut overlay_db,
241+
candidate_hash,
242+
candidate_receipt,
243+
session,
244+
valid,
245+
clock.now(),
246+
)
247+
.await?;
248+
} else {
249+
gum::warn!(target: LOG_TARGET, ?outcome, "Dispute participation failed");
250+
}
265251
default_confirm
266252
},
267-
FromOrchestra::Signal(OverseerSignal::BlockFinalized(_, n)) => {
268-
gum::trace!(target: LOG_TARGET, "OverseerSignal::BlockFinalized");
269-
self.scraper.process_finalized_block(&n);
270-
default_confirm
253+
MuxedMessage::Subsystem(msg) => match msg {
254+
FromOrchestra::Signal(OverseerSignal::Conclude) => return Ok(()),
255+
FromOrchestra::Signal(OverseerSignal::ActiveLeaves(update)) => {
256+
gum::trace!(target: LOG_TARGET, "OverseerSignal::ActiveLeaves");
257+
self.process_active_leaves_update(
258+
ctx,
259+
&mut overlay_db,
260+
update,
261+
clock.now(),
262+
)
263+
.await?;
264+
default_confirm
265+
},
266+
FromOrchestra::Signal(OverseerSignal::BlockFinalized(_, n)) => {
267+
gum::trace!(target: LOG_TARGET, "OverseerSignal::BlockFinalized");
268+
self.scraper.process_finalized_block(&n);
269+
default_confirm
270+
},
271+
FromOrchestra::Communication { msg } =>
272+
self.handle_incoming(ctx, &mut overlay_db, msg, clock.now()).await?,
271273
},
272-
FromOrchestra::Communication { msg } =>
273-
self.handle_incoming(ctx, &mut overlay_db, msg, clock.now()).await?,
274-
},
275-
};
274+
};
276275

277276
if !overlay_db.is_empty() {
278277
let ops = overlay_db.into_write_ops();

node/core/pvf/worker/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ substrate-build-script-utils = { git = "https://github.com/paritytech/substrate"
4343
[dev-dependencies]
4444
adder = { package = "test-parachain-adder", path = "../../../../parachain/test-parachains/adder" }
4545
halt = { package = "test-parachain-halt", path = "../../../../parachain/test-parachains/halt" }
46-
tempfile = "3.3.0"
4746

4847
[features]
4948
jemalloc-allocator = ["dep:tikv-jemalloc-ctl"]

node/core/pvf/worker/src/execute.rs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use polkadot_node_core_pvf::{
3131
};
3232
use polkadot_parachain::primitives::ValidationResult;
3333
use std::{
34-
path::{Path, PathBuf},
34+
path::PathBuf,
3535
sync::{mpsc::channel, Arc},
3636
time::Duration,
3737
};
@@ -97,6 +97,20 @@ pub fn worker_entrypoint(socket_path: &str, node_version: Option<&str>) {
9797
artifact_path.display(),
9898
);
9999

100+
// Get the artifact bytes.
101+
//
102+
// We do this outside the thread so that we can lock down filesystem access there.
103+
let compiled_artifact_blob = match std::fs::read(artifact_path) {
104+
Ok(bytes) => bytes,
105+
Err(err) => {
106+
let response = Response::InternalError(
107+
InternalValidationError::CouldNotOpenFile(err.to_string()),
108+
);
109+
send_response(&mut stream, response).await?;
110+
continue
111+
},
112+
};
113+
100114
// Conditional variable to notify us when a thread is done.
101115
let condvar = thread::get_condvar();
102116

@@ -116,7 +130,12 @@ pub fn worker_entrypoint(socket_path: &str, node_version: Option<&str>) {
116130
let execute_thread = thread::spawn_worker_thread_with_stack_size(
117131
"execute thread",
118132
move || {
119-
validate_using_artifact(&artifact_path, &params, executor_2, cpu_time_start)
133+
validate_using_artifact(
134+
&compiled_artifact_blob,
135+
&params,
136+
executor_2,
137+
cpu_time_start,
138+
)
120139
},
121140
Arc::clone(&condvar),
122141
WaitOutcome::Finished,
@@ -167,23 +186,16 @@ pub fn worker_entrypoint(socket_path: &str, node_version: Option<&str>) {
167186
}
168187

169188
fn validate_using_artifact(
170-
artifact_path: &Path,
189+
compiled_artifact_blob: &[u8],
171190
params: &[u8],
172191
executor: Executor,
173192
cpu_time_start: ProcessTime,
174193
) -> Response {
175-
// Check here if the file exists, because the error from Substrate is not match-able.
176-
// TODO: Re-evaluate after <https://github.com/paritytech/substrate/issues/13860>.
177-
let file_metadata = std::fs::metadata(artifact_path);
178-
if let Err(err) = file_metadata {
179-
return Response::InternalError(InternalValidationError::CouldNotOpenFile(err.to_string()))
180-
}
181-
182194
let descriptor_bytes = match unsafe {
183195
// SAFETY: this should be safe since the compiled artifact passed here comes from the
184196
// file created by the prepare workers. These files are obtained by calling
185197
// [`executor_intf::prepare`].
186-
executor.execute(artifact_path.as_ref(), params)
198+
executor.execute(compiled_artifact_blob, params)
187199
} {
188200
Err(err) => return Response::format_invalid("execute", &err),
189201
Ok(d) => d,

node/core/pvf/worker/src/executor_intf.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,14 @@
1818
1919
use polkadot_primitives::{ExecutorParam, ExecutorParams};
2020
use sc_executor_common::{
21+
error::WasmError,
2122
runtime_blob::RuntimeBlob,
2223
wasm_runtime::{HeapAllocStrategy, InvokeMethod, WasmModule as _},
2324
};
24-
use sc_executor_wasmtime::{Config, DeterministicStackLimit, Semantics};
25+
use sc_executor_wasmtime::{Config, DeterministicStackLimit, Semantics, WasmtimeRuntime};
2526
use sp_core::storage::{ChildInfo, TrackedStorageKey};
2627
use sp_externalities::MultiRemovalResults;
27-
use std::{
28-
any::{Any, TypeId},
29-
path::Path,
30-
};
28+
use std::any::{Any, TypeId};
3129

3230
// Wasmtime powers the Substrate Executor. It compiles the wasm bytecode into native code.
3331
// That native code does not create any stacks and just reuses the stack of the thread that
@@ -206,7 +204,7 @@ impl Executor {
206204
/// Failure to adhere to these requirements might lead to crashes and arbitrary code execution.
207205
pub unsafe fn execute(
208206
&self,
209-
compiled_artifact_path: &Path,
207+
compiled_artifact_blob: &[u8],
210208
params: &[u8],
211209
) -> Result<Vec<u8>, String> {
212210
let mut extensions = sp_externalities::Extensions::new();
@@ -216,17 +214,33 @@ impl Executor {
216214
let mut ext = ValidationExternalities(extensions);
217215

218216
match sc_executor::with_externalities_safe(&mut ext, || {
219-
let runtime = sc_executor_wasmtime::create_runtime_from_artifact::<HostFunctions>(
220-
compiled_artifact_path,
221-
self.config.clone(),
222-
)?;
217+
let runtime = self.create_runtime_from_bytes(compiled_artifact_blob)?;
223218
runtime.new_instance()?.call(InvokeMethod::Export("validate_block"), params)
224219
}) {
225220
Ok(Ok(ok)) => Ok(ok),
226221
Ok(Err(err)) | Err(err) => Err(err),
227222
}
228223
.map_err(|err| format!("execute error: {:?}", err))
229224
}
225+
226+
/// Constructs the runtime for the given PVF, given the artifact bytes.
227+
///
228+
/// # Safety
229+
///
230+
/// The caller must ensure that the compiled artifact passed here was:
231+
/// 1) produced by [`prepare`],
232+
/// 2) was not modified,
233+
///
234+
/// Failure to adhere to these requirements might lead to crashes and arbitrary code execution.
235+
pub unsafe fn create_runtime_from_bytes(
236+
&self,
237+
compiled_artifact_blob: &[u8],
238+
) -> Result<WasmtimeRuntime, WasmError> {
239+
sc_executor_wasmtime::create_runtime_from_artifact_bytes::<HostFunctions>(
240+
compiled_artifact_blob,
241+
self.config.clone(),
242+
)
243+
}
230244
}
231245

232246
type HostFunctions = (

node/core/pvf/worker/src/testing.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,13 @@ pub fn validate_candidate(
3333
.expect("Decompressing code failed");
3434

3535
let blob = prevalidate(&code)?;
36-
let artifact = prepare(blob, &ExecutorParams::default())?;
37-
let tmpdir = tempfile::tempdir()?;
38-
let artifact_path = tmpdir.path().join("blob");
39-
std::fs::write(&artifact_path, &artifact)?;
36+
let compiled_artifact_blob = prepare(blob, &ExecutorParams::default())?;
4037

4138
let executor = Executor::new(ExecutorParams::default())?;
4239
let result = unsafe {
4340
// SAFETY: This is trivially safe since the artifact is obtained by calling `prepare`
4441
// and is written into a temporary directory in an unmodified state.
45-
executor.execute(&artifact_path, params)?
42+
executor.execute(&compiled_artifact_blob, params)?
4643
};
4744

4845
Ok(result)

node/metrics/src/tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ async fn runtime_can_publish_metrics() {
6161
// Start validator Bob.
6262
let _bob = run_validator_node(bob_config, None);
6363

64-
// Wait for Alice to author two blocks.
65-
alice.wait_for_blocks(2).await;
64+
// Wait for Alice to see two finalized blocks.
65+
alice.wait_for_finalized_blocks(2).await;
6666

6767
let metrics_uri = format!("http://localhost:{}/metrics", DEFAULT_PROMETHEUS_PORT);
6868
let metrics = scrape_prometheus_metrics(&metrics_uri).await;

node/network/availability-recovery/src/tests.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,9 @@ async fn overseer_signal(
172172
.send(FromOrchestra::Signal(signal))
173173
.timeout(TIMEOUT)
174174
.await
175-
.expect("10ms is more than enough for sending signals.");
175+
.unwrap_or_else(|| {
176+
panic!("{}ms is more than enough for sending signals.", TIMEOUT.as_millis())
177+
});
176178
}
177179

178180
async fn overseer_send(
@@ -184,7 +186,9 @@ async fn overseer_send(
184186
.send(FromOrchestra::Communication { msg })
185187
.timeout(TIMEOUT)
186188
.await
187-
.expect("10ms is more than enough for sending messages.");
189+
.unwrap_or_else(|| {
190+
panic!("{}ms is more than enough for sending messages.", TIMEOUT.as_millis())
191+
});
188192
}
189193

190194
async fn overseer_recv(

node/network/bitfield-distribution/src/tests.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,12 @@ use sp_keystore::{testing::MemoryKeystore, Keystore, KeystorePtr};
4141

4242
use std::{iter::FromIterator as _, sync::Arc, time::Duration};
4343

44+
const TIMEOUT: Duration = Duration::from_millis(50);
4445
macro_rules! launch {
4546
($fut:expr) => {
46-
$fut.timeout(Duration::from_millis(10))
47-
.await
48-
.expect("10ms is more than enough for sending messages.")
47+
$fut.timeout(TIMEOUT).await.unwrap_or_else(|| {
48+
panic!("{}ms is more than enough for sending messages.", TIMEOUT.as_millis())
49+
});
4950
};
5051
}
5152

@@ -220,7 +221,7 @@ fn receive_invalid_signature() {
220221
));
221222

222223
// reputation doesn't change due to one_job_per_validator check
223-
assert!(handle.recv().timeout(Duration::from_millis(10)).await.is_none());
224+
assert!(handle.recv().timeout(TIMEOUT).await.is_none());
224225

225226
launch!(handle_network_msg(
226227
&mut ctx,
@@ -523,7 +524,7 @@ fn do_not_relay_message_twice() {
523524
);
524525

525526
// There shouldn't be any other message
526-
assert!(handle.recv().timeout(Duration::from_millis(10)).await.is_none());
527+
assert!(handle.recv().timeout(TIMEOUT).await.is_none());
527528
});
528529
}
529530

node/network/collator-protocol/src/collator_side/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use super::*;
1919
use std::{collections::HashSet, sync::Arc, time::Duration};
2020

2121
use assert_matches::assert_matches;
22-
use futures::{executor, future, Future, SinkExt};
22+
use futures::{executor, future, Future};
2323
use futures_timer::Delay;
2424

2525
use parity_scale_codec::{Decode, Encode};

node/network/dispute-distribution/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ lru = "0.9.0"
2525
indexmap = "1.9.1"
2626

2727
[dev-dependencies]
28+
async-channel = "1.8.0"
2829
async-trait = "0.1.57"
2930
polkadot-node-subsystem-test-helpers = { path = "../../subsystem-test-helpers" }
3031
sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "master" }

0 commit comments

Comments
 (0)