referrerpolicy=no-referrer-when-downgrade

polkadot_node_core_pvf_checker/
runtime_api.rs

1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot.  If not, see <http://www.gnu.org/licenses/>.
16
17use crate::LOG_TARGET;
18use futures::channel::oneshot;
19use polkadot_node_subsystem::{
20	errors::RuntimeApiError as RuntimeApiSubsystemError,
21	messages::{RuntimeApiMessage, RuntimeApiRequest},
22	SubsystemSender,
23};
24use polkadot_primitives::{
25	Hash, PvfCheckStatement, SessionIndex, ValidationCodeHash, ValidatorId, ValidatorSignature,
26};
27
28pub(crate) async fn session_index_for_child(
29	sender: &mut impl SubsystemSender<RuntimeApiMessage>,
30	relay_parent: Hash,
31) -> Result<SessionIndex, RuntimeRequestError> {
32	let (tx, rx) = oneshot::channel();
33	runtime_api_request(sender, relay_parent, RuntimeApiRequest::SessionIndexForChild(tx), rx).await
34}
35
36pub(crate) async fn validators(
37	sender: &mut impl SubsystemSender<RuntimeApiMessage>,
38	relay_parent: Hash,
39) -> Result<Vec<ValidatorId>, RuntimeRequestError> {
40	let (tx, rx) = oneshot::channel();
41	runtime_api_request(sender, relay_parent, RuntimeApiRequest::Validators(tx), rx).await
42}
43
44pub(crate) async fn submit_pvf_check_statement(
45	sender: &mut impl SubsystemSender<RuntimeApiMessage>,
46	relay_parent: Hash,
47	stmt: PvfCheckStatement,
48	signature: ValidatorSignature,
49) -> Result<(), RuntimeRequestError> {
50	let (tx, rx) = oneshot::channel();
51	runtime_api_request(
52		sender,
53		relay_parent,
54		RuntimeApiRequest::SubmitPvfCheckStatement(stmt, signature, tx),
55		rx,
56	)
57	.await
58}
59
60pub(crate) async fn pvfs_require_precheck(
61	sender: &mut impl SubsystemSender<RuntimeApiMessage>,
62	relay_parent: Hash,
63) -> Result<Vec<ValidationCodeHash>, RuntimeRequestError> {
64	let (tx, rx) = oneshot::channel();
65	runtime_api_request(sender, relay_parent, RuntimeApiRequest::PvfsRequirePrecheck(tx), rx).await
66}
67
68#[derive(Debug)]
69pub(crate) enum RuntimeRequestError {
70	NotSupported,
71	ApiError,
72	CommunicationError,
73}
74
75pub(crate) async fn runtime_api_request<T>(
76	sender: &mut impl SubsystemSender<RuntimeApiMessage>,
77	relay_parent: Hash,
78	request: RuntimeApiRequest,
79	receiver: oneshot::Receiver<Result<T, RuntimeApiSubsystemError>>,
80) -> Result<T, RuntimeRequestError> {
81	sender
82		.send_message(RuntimeApiMessage::Request(relay_parent, request).into())
83		.await;
84
85	receiver
86		.await
87		.map_err(|_| {
88			gum::debug!(target: LOG_TARGET, ?relay_parent, "Runtime API request dropped");
89			RuntimeRequestError::CommunicationError
90		})
91		.and_then(|res| {
92			res.map_err(|e| {
93				use RuntimeApiSubsystemError::*;
94				match e {
95					Execution { .. } => {
96						gum::debug!(
97							target: LOG_TARGET,
98							?relay_parent,
99							err = ?e,
100							"Runtime API request internal error"
101						);
102						RuntimeRequestError::ApiError
103					},
104					NotSupported { .. } => RuntimeRequestError::NotSupported,
105				}
106			})
107		})
108}