Skip to content

Commit

Permalink
middleware to inject missing block hash/number
Browse files Browse the repository at this point in the history
  • Loading branch information
ermalkaleci committed Feb 5, 2023
1 parent 4fc13fb commit fb7b1f1
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 18 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@

# These are backup files generated by rustfmt
**/*.rs.bk
.idea
20 changes: 10 additions & 10 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,41 @@ rpcs:

- method: chain_getBlockHash
cache: true
with_block_number: true
with_block_number: 0

- method: chain_getHeader
cache: true
with_block_hash: true
with_block_hash: 0

- method: chain_getBlock
cache: true
with_block_hash: true
with_block_hash: 0

- method: chain_getFinalizedHead

- method: state_getRuntimeVersion
cache: true
with_block_hash: true
with_block_hash: 0

- method: state_getMetadata
cache: true
with_block_hash: true
with_block_hash: 0

- method: state_getStorage
cache: true
with_block_hash: true
with_block_hash: 1

- method: state_getKeysPaged
cache: true
with_block_hash: true
with_block_hash: 3

- method: state_queryStorageAt
cache: true
with_block_hash: true
with_block_hash: 1

- method: state_call
cache: true
with_block_hash: true
with_block_hash: 2

- method: system_chain
cache: true
Expand All @@ -70,7 +70,7 @@ rpcs:

- method: system_dryRun
cache: true
with_block_hash: true
with_block_hash: 1

- method: system_accountNextIndex

Expand Down
18 changes: 18 additions & 0 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@ pub struct Api {
finalized_head: Arc<RwLock<Option<(JsonValue, u64)>>>,
}

impl Api {
pub async fn get_block_number(&self) -> Option<JsonValue> {
self.head
.read()
.await
.as_ref()
.map(|(_, number)| JsonValue::from(*number))
}

pub async fn get_block_hash(&self) -> Option<JsonValue> {
self.head
.read()
.await
.as_ref()
.map(|(hash, _)| hash.clone())
}
}

impl Api {
pub fn new(client: Arc<Client>) -> Self {
let this = Self {
Expand Down
7 changes: 2 additions & 5 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,8 @@ pub struct RpcMethod {
#[serde(default)]
pub cache: bool,

#[serde(default)]
pub with_block_hash: bool,

#[serde(default)]
pub with_block_number: bool,
pub with_block_hash: Option<usize>,
pub with_block_number: Option<usize>,
}

#[derive(Deserialize, Debug)]
Expand Down
65 changes: 65 additions & 0 deletions src/middleware/inject_params.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
use async_trait::async_trait;
use jsonrpsee::{
core::{Error, JsonValue, __reexports::serde_json},
types::Params,
};
use std::sync::Arc;

use super::{Middleware, NextFn};
use crate::{api::Api, middleware::call::CallRequest};

pub enum Inject {
BlockHashAt(usize),
BlockNumberAt(usize),
}

pub struct InjectParamsMiddleware {
api: Arc<Api>,
inject: Inject,
}

impl InjectParamsMiddleware {
pub fn new(api: Arc<Api>, inject: Inject) -> Self {
Self { api, inject }
}

async fn needs_to_inject(&self, params_len: usize) -> Option<JsonValue> {
match self.inject {
Inject::BlockHashAt(hash_index) => {
if params_len == hash_index {
// block hash is missing
return self.api.get_block_hash().await;
}
}
Inject::BlockNumberAt(number_index) => {
if params_len == number_index {
// block number is missing
return self.api.get_block_number().await;
}
}
}
None
}
}

#[async_trait]
impl Middleware<CallRequest, Result<JsonValue, Error>> for InjectParamsMiddleware {
async fn call(
&self,
mut request: CallRequest,
next: NextFn<CallRequest, Result<JsonValue, Error>>,
) -> Result<JsonValue, Error> {
let params = request.params.parse::<JsonValue>()?;

if let Some(params) = params.to_owned().as_array_mut() {
if let Some(param) = self.needs_to_inject(params.len()).await {
log::debug!("Injected param {} to method {}", &param, request.method);
params.push(param);
request.params =
Params::new(Some(serde_json::to_string(&params)?.as_str())).into_owned();
}
}

next(request).await
}
}
1 change: 1 addition & 0 deletions src/middleware/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use async_trait::async_trait;
use futures::{future::BoxFuture, FutureExt};

pub mod call;
pub mod inject_params;
pub mod subscription;

type NextFn<Request, Result> = Box<dyn FnOnce(Request) -> BoxFuture<'static, Result> + Send + Sync>;
Expand Down
24 changes: 21 additions & 3 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ use crate::{
config::Config,
middleware::{
call::{self, CallRequest},
inject_params::{Inject, InjectParamsMiddleware},
subscription::{self, SubscriptionRequest},
Middlewares,
Middleware, Middlewares,
},
};

Expand All @@ -36,13 +37,30 @@ pub async fn start_server(
let mut module = RpcModule::new(());

let client = Arc::new(client);
let _api = Api::new(client.clone());
let api = Arc::new(Api::new(client.clone()));

let upstream = Arc::new(call::UpstreamMiddleware::new(client.clone()));

for method in &config.rpcs.methods {
let mut list: Vec<Arc<dyn Middleware<_, _>>> = vec![];

if let Some(hash_index) = method.with_block_hash {
list.push(Arc::new(InjectParamsMiddleware::new(
api.clone(),
Inject::BlockHashAt(hash_index),
)));
}
if let Some(number_index) = method.with_block_number {
list.push(Arc::new(InjectParamsMiddleware::new(
api.clone(),
Inject::BlockNumberAt(number_index),
)));
}

list.push(upstream.clone());

let middlewares = Arc::new(Middlewares::new(
vec![upstream.clone()],
list,
Arc::new(|_| {
async {
Err(
Expand Down

0 comments on commit fb7b1f1

Please sign in to comment.