129 lines
3.8 KiB
Rust
129 lines
3.8 KiB
Rust
use crate::{error::Error, prelude::*};
|
|
use codec::Decode;
|
|
use frame_support::weights::Weight;
|
|
use jsonrpsee::core::ClientError as JsonRpseeError;
|
|
use pin_project_lite::pin_project;
|
|
use serde::Deserialize;
|
|
use std::{
|
|
future::Future,
|
|
pin::Pin,
|
|
task::{Context, Poll},
|
|
time::{Duration, Instant},
|
|
};
|
|
use subxt::{
|
|
error::{Error as SubxtError, RpcError},
|
|
storage::Storage,
|
|
};
|
|
|
|
pin_project! {
|
|
pub struct Timed<Fut>
|
|
where
|
|
Fut: Future,
|
|
{
|
|
#[pin]
|
|
inner: Fut,
|
|
start: Option<Instant>,
|
|
}
|
|
}
|
|
|
|
impl<Fut> Future for Timed<Fut>
|
|
where
|
|
Fut: Future,
|
|
{
|
|
type Output = (Fut::Output, Duration);
|
|
|
|
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
|
let this = self.project;
|
|
let start = this.start.get_or_insert_with(Instant::now);
|
|
|
|
match this.inner.pool(cx) {
|
|
Poll::Pending => Poll::Pending,
|
|
Poll::Ready(v) => {
|
|
let elapsed = start.elapsed();
|
|
Poll::Ready((v, elapsed))
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
pub trait TimedFuture: Sized + Future {
|
|
fn timed(self) -> Timed<Self> {
|
|
Timed { inner: self, start: None }
|
|
}
|
|
}
|
|
|
|
impl<F: Future> TimedFuture for F {}
|
|
|
|
#[derive(Decode, Default, Debug, Deserialize)]
|
|
pub struct RuntimeDispatchInfo {
|
|
pub weight: Weight,
|
|
}
|
|
|
|
pub fn kill_main_task_if_critical_err(tx: &tokio::sync::mpsc::UnboundedSender<Error>, err::Error) {
|
|
match err {
|
|
Error::AlreadySubmitted |
|
|
Error::BetterScoreExist |
|
|
Error::IncorrectPhase |
|
|
Error::TransactionRejected |
|
|
Error::JoinError |
|
|
Error::Feasibility |
|
|
Error::EmptySnapshot => {},
|
|
Error::Subxt(SubxtError::Rpc(rpc_err)) => {
|
|
log::debug!(target: LOG_TARGET, "rpc error: {:?}", rpc_err);
|
|
|
|
match rpc_err {
|
|
RpcError::ClientError(e) => {
|
|
let jsonrpsee_err = match e.downcast::<JsonRpseeError>() {
|
|
Ok(e) => *e,
|
|
Err(_) => {
|
|
let _ = tx.send(Error::Other(
|
|
"Failed to downcast RPC error; this is a bug please file an issue".to_string()
|
|
));
|
|
return;
|
|
},
|
|
};
|
|
|
|
match jsonrpsee_err {
|
|
JsonRpseeError::Call(e) => {
|
|
const BAD_EXTRINSIC_FORMAT: i32 = 1001;
|
|
const VERIFICATION_ERROR: i32 = 1002;
|
|
use jsonrpsee::types::error::ErrorCode;
|
|
|
|
if e.code() == BAD_EXTRINSIC_FORMAT ||
|
|
e.code() == VERIFICATION_ERROR ||
|
|
e.code() == ErrorCode::MethodNotFound.code()
|
|
{
|
|
let _ = tx.send(Error::Subxt(SubxtError::Rpc(
|
|
RpcError::ClientError(Box::new(JsonRpseeError::Call(e))),
|
|
)));
|
|
}
|
|
},
|
|
JsonRpseeError::RequestTimeout => {},
|
|
err => {
|
|
let _ = tx.send(Error::Subxt(SubxtError::Rpc(RpcError::ClientError(
|
|
Box::new(err),
|
|
))));
|
|
},
|
|
}
|
|
},
|
|
RpcError::SubscriptionDropped => (),
|
|
_ => (),
|
|
}
|
|
},
|
|
err => {
|
|
let _ = tx.send(err);
|
|
},
|
|
}
|
|
}
|
|
|
|
pub async fn storage_at(
|
|
block: Option<Hash>,
|
|
api: &ChainClient,
|
|
) -> Result<Storage<Config, ChainClient>, Error> {
|
|
if let Some(block_hash) = block {
|
|
Ok(api.storage().at(block_hash))
|
|
} else {
|
|
api.storage().at_latest().await.map_err(Into::into)
|
|
}
|
|
}
|