Add new Runtime API messages and make runtime API request fallible (#1485)

* polkadot-subsystem: update runtime API message types

* update all networking subsystems to use fallible runtime APIs

* fix bitfield-signing and make it use new runtime APIs

* port candidate-backing to handle runtime API errors and new types

* remove old runtime API messages

* remove unused imports

* fix grumbles

* fix backing tests
This commit is contained in:
Robert Habermeier
2020-07-28 14:02:39 -04:00
committed by GitHub
parent d234ba38bb
commit c8cdfbfd17
9 changed files with 269 additions and 140 deletions
@@ -161,17 +161,23 @@ impl BitfieldDistribution {
for relay_parent in activated {
trace!(target: "bitd", "Start {:?}", relay_parent);
// query basic system parameters once
let (validator_set, signing_context) =
query_basics(&mut ctx, relay_parent).await?;
let _ = state.per_relay_parent.insert(
relay_parent,
PerRelayParentData {
signing_context,
validator_set,
..Default::default()
},
);
if let Some((validator_set, signing_context)) =
query_basics(&mut ctx, relay_parent).await?
{
// If our runtime API fails, we don't take down the node,
// but we might alter peers' reputations erroneously as a result
// of not having the correct bookkeeping. If we have lost a race
// with state pruning, it is unlikely that peers will be sending
// us anything to do with this relay-parent anyway.
let _ = state.per_relay_parent.insert(
relay_parent,
PerRelayParentData {
signing_context,
validator_set,
..Default::default()
},
);
}
}
for relay_parent in deactivated {
@@ -562,12 +568,12 @@ where
async fn query_basics<Context>(
ctx: &mut Context,
relay_parent: Hash,
) -> SubsystemResult<(Vec<ValidatorId>, SigningContext)>
) -> SubsystemResult<Option<(Vec<ValidatorId>, SigningContext)>>
where
Context: SubsystemContext<Message = BitfieldDistributionMessage>,
{
let (validators_tx, validators_rx) = oneshot::channel();
let (signing_tx, signing_rx) = oneshot::channel();
let (session_tx, session_rx) = oneshot::channel();
let query_validators = AllMessages::RuntimeApi(RuntimeApiMessage::Request(
relay_parent.clone(),
@@ -576,13 +582,22 @@ where
let query_signing = AllMessages::RuntimeApi(RuntimeApiMessage::Request(
relay_parent.clone(),
RuntimeApiRequest::SigningContext(signing_tx),
RuntimeApiRequest::SessionIndexForChild(session_tx),
));
ctx.send_messages(std::iter::once(query_validators).chain(std::iter::once(query_signing)))
.await?;
Ok((validators_rx.await?, signing_rx.await?))
match (validators_rx.await?, session_rx.await?) {
(Ok(v), Ok(s)) => Ok(Some((
v,
SigningContext { parent_hash: relay_parent, session_index: s },
))),
(Err(e), _) | (_, Err(e)) => {
warn!(target: "bitd", "Failed to fetch basics from runtime API: {:?}", e);
Ok(None)
}
}
}
#[cfg(test)]
@@ -115,10 +115,27 @@ async fn handle_signal(
RuntimeApiRequest::Validators(vals_tx),
))).await?;
let n_validators = match vals_rx.await? {
Ok(v) => v.len(),
Err(e) => {
log::warn!(target: "pov_distribution",
"Error fetching validators from runtime API for active leaf: {:?}",
e
);
// Not adding bookkeeping here might make us behave funny, but we
// shouldn't take down the node on spurious runtime API errors.
//
// and this is "behave funny" as in be bad at our job, but not in any
// slashable or security-related way.
continue;
}
};
state.relay_parent_state.insert(relay_parent, BlockBasedState {
known: HashMap::new(),
fetching: HashMap::new(),
n_validators: vals_rx.await?.len(),
n_validators: n_validators,
});
}
@@ -847,17 +847,37 @@ async fn run(
let (session_tx, session_rx) = oneshot::channel();
let val_message = AllMessages::RuntimeApi(
RuntimeApiMessage::Request(relay_parent, RuntimeApiRequest::Validators(val_tx)),
RuntimeApiMessage::Request(
relay_parent,
RuntimeApiRequest::Validators(val_tx),
),
);
let session_message = AllMessages::RuntimeApi(
RuntimeApiMessage::Request(relay_parent, RuntimeApiRequest::SigningContext(session_tx)),
RuntimeApiMessage::Request(
relay_parent,
RuntimeApiRequest::SessionIndexForChild(session_tx),
),
);
ctx.send_messages(
std::iter::once(val_message).chain(std::iter::once(session_message))
).await?;
(val_rx.await?, session_rx.await?.session_index)
match (val_rx.await?, session_rx.await?) {
(Ok(v), Ok(s)) => (v, s),
(Err(e), _) | (_, Err(e)) => {
log::warn!(
target: "statement_distribution",
"Failed to fetch runtime API data for active leaf: {:?}",
e,
);
// Lacking this bookkeeping might make us behave funny, although
// not in any slashable way. But we shouldn't take down the node
// on what are likely spurious runtime API errors.
continue;
}
}
};
active_heads.entry(relay_parent)