rpc: backpressured RPC server (bump jsonrpsee 0.20) (#1313)

This is a rather big change in jsonrpsee, the major things in this bump
are:
- Server backpressure (the subscription impls are modified to deal with
that)
- Allow custom error types / return types (remove jsonrpsee::core::Error
and jsonrpee::core::CallError)
- Bug fixes (graceful shutdown in particular not used by substrate
anyway)
   - Less dependencies for the clients in particular
   - Return type requires Clone in method call responses
   - Moved to tokio channels
   - Async subscription API (not used in this PR)

Major changes in this PR:
- The subscriptions are now bounded and if subscription can't keep up
with the server it is dropped
- CLI: add parameter to configure the jsonrpc server bounded message
buffer (default is 64)
- Add our own subscription helper to deal with the unbounded streams in
substrate

The most important things in this PR to review is the added helpers
functions in `substrate/client/rpc/src/utils.rs` and the rest is pretty
much chore.

Regarding the "bounded buffer limit" it may cause the server to handle
the JSON-RPC calls
slower than before.

The message size limit is bounded by "--rpc-response-size" thus "by
default 10MB * 64 = 640MB"
but the subscription message size is not covered by this limit and could
be capped as well.

Hopefully the last release prior to 1.0, sorry in advance for a big PR

Previous attempt: https://github.com/paritytech/substrate/pull/13992

Resolves https://github.com/paritytech/polkadot-sdk/issues/748, resolves
https://github.com/paritytech/polkadot-sdk/issues/627
This commit is contained in:
Niklas Adolfsson
2024-01-23 09:55:13 +01:00
committed by GitHub
parent 76c37c930b
commit e16ef0861f
117 changed files with 1245 additions and 1090 deletions
+14 -15
View File
@@ -23,7 +23,7 @@ use codec::{self, Codec, Decode, Encode};
use jsonrpsee::{
core::{async_trait, RpcResult},
proc_macros::rpc,
types::error::{CallError, ErrorObject},
types::error::ErrorObject,
};
use sc_rpc_api::DenyUnsafe;
@@ -103,11 +103,11 @@ where
let best = self.client.info().best_hash;
let nonce = api.account_nonce(best, account.clone()).map_err(|e| {
CallError::Custom(ErrorObject::owned(
ErrorObject::owned(
Error::RuntimeError.into(),
"Unable to query nonce.",
Some(e.to_string()),
))
)
})?;
Ok(adjust_nonce(&*self.pool, account, nonce))
}
@@ -125,28 +125,28 @@ where
let uxt: <Block as traits::Block>::Extrinsic =
Decode::decode(&mut &*extrinsic).map_err(|e| {
CallError::Custom(ErrorObject::owned(
ErrorObject::owned(
Error::DecodeError.into(),
"Unable to dry run extrinsic",
Some(e.to_string()),
))
)
})?;
let api_version = api
.api_version::<dyn BlockBuilder<Block>>(best_hash)
.map_err(|e| {
CallError::Custom(ErrorObject::owned(
ErrorObject::owned(
Error::RuntimeError.into(),
"Unable to dry run extrinsic.",
Some(e.to_string()),
))
)
})?
.ok_or_else(|| {
CallError::Custom(ErrorObject::owned(
ErrorObject::owned(
Error::RuntimeError.into(),
"Unable to dry run extrinsic.",
Some(format!("Could not find `BlockBuilder` api for block `{:?}`.", best_hash)),
))
)
})?;
let result = if api_version < 6 {
@@ -154,19 +154,19 @@ where
api.apply_extrinsic_before_version_6(best_hash, uxt)
.map(legacy::byte_sized_error::convert_to_latest)
.map_err(|e| {
CallError::Custom(ErrorObject::owned(
ErrorObject::owned(
Error::RuntimeError.into(),
"Unable to dry run extrinsic.",
Some(e.to_string()),
))
)
})?
} else {
api.apply_extrinsic(best_hash, uxt).map_err(|e| {
CallError::Custom(ErrorObject::owned(
ErrorObject::owned(
Error::RuntimeError.into(),
"Unable to dry run extrinsic.",
Some(e.to_string()),
))
)
})?
};
@@ -216,7 +216,6 @@ mod tests {
use assert_matches::assert_matches;
use futures::executor::block_on;
use jsonrpsee::{core::Error as JsonRpseeError, types::error::CallError};
use sc_transaction_pool::BasicPool;
use sp_runtime::{
transaction_validity::{InvalidTransaction, TransactionValidityError},
@@ -274,7 +273,7 @@ mod tests {
// when
let res = accounts.dry_run(vec![].into(), None).await;
assert_matches!(res, Err(JsonRpseeError::Call(CallError::Custom(e))) => {
assert_matches!(res, Err(e) => {
assert!(e.message().contains("RPC call is unsafe to be called externally"));
});
}