1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use crate::LOG_TARGET;
use futures::channel::oneshot;
use polkadot_node_subsystem::{
errors::RuntimeApiError as RuntimeApiSubsystemError,
messages::{RuntimeApiMessage, RuntimeApiRequest},
SubsystemSender,
};
use polkadot_primitives::v2::{
Hash, PvfCheckStatement, SessionIndex, ValidationCodeHash, ValidatorId, ValidatorSignature,
};
pub(crate) async fn session_index_for_child(
sender: &mut impl SubsystemSender<RuntimeApiMessage>,
relay_parent: Hash,
) -> Result<SessionIndex, RuntimeRequestError> {
let (tx, rx) = oneshot::channel();
runtime_api_request(sender, relay_parent, RuntimeApiRequest::SessionIndexForChild(tx), rx).await
}
pub(crate) async fn validators(
sender: &mut impl SubsystemSender<RuntimeApiMessage>,
relay_parent: Hash,
) -> Result<Vec<ValidatorId>, RuntimeRequestError> {
let (tx, rx) = oneshot::channel();
runtime_api_request(sender, relay_parent, RuntimeApiRequest::Validators(tx), rx).await
}
pub(crate) async fn submit_pvf_check_statement(
sender: &mut impl SubsystemSender<RuntimeApiMessage>,
relay_parent: Hash,
stmt: PvfCheckStatement,
signature: ValidatorSignature,
) -> Result<(), RuntimeRequestError> {
let (tx, rx) = oneshot::channel();
runtime_api_request(
sender,
relay_parent,
RuntimeApiRequest::SubmitPvfCheckStatement(stmt, signature, tx),
rx,
)
.await
}
pub(crate) async fn pvfs_require_precheck(
sender: &mut impl SubsystemSender<RuntimeApiMessage>,
relay_parent: Hash,
) -> Result<Vec<ValidationCodeHash>, RuntimeRequestError> {
let (tx, rx) = oneshot::channel();
runtime_api_request(sender, relay_parent, RuntimeApiRequest::PvfsRequirePrecheck(tx), rx).await
}
#[derive(Debug)]
pub(crate) enum RuntimeRequestError {
NotSupported,
ApiError,
CommunicationError,
}
pub(crate) async fn runtime_api_request<T>(
sender: &mut impl SubsystemSender<RuntimeApiMessage>,
relay_parent: Hash,
request: RuntimeApiRequest,
receiver: oneshot::Receiver<Result<T, RuntimeApiSubsystemError>>,
) -> Result<T, RuntimeRequestError> {
sender
.send_message(RuntimeApiMessage::Request(relay_parent, request).into())
.await;
receiver
.await
.map_err(|_| {
gum::debug!(target: LOG_TARGET, ?relay_parent, "Runtime API request dropped");
RuntimeRequestError::CommunicationError
})
.and_then(|res| {
res.map_err(|e| {
use RuntimeApiSubsystemError::*;
match e {
Execution { .. } => {
gum::debug!(
target: LOG_TARGET,
?relay_parent,
err = ?e,
"Runtime API request internal error"
);
RuntimeRequestError::ApiError
},
NotSupported { .. } => RuntimeRequestError::NotSupported,
}
})
})
}