Skip to content

Commit

Permalink
Fix batched reqs (#315)
Browse files Browse the repository at this point in the history
Co-authored-by: Trantorian1 <[email protected]>
Co-authored-by: antiyro <[email protected]>
  • Loading branch information
3 people authored Oct 14, 2024
1 parent fb38719 commit b79390b
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Next release

- fix(rpc): handle batched requests in middleware
- chore: padded devnet address display with 64 chars
- feat(script): added more capabilities to the launcher script
- fix(fgw): sync from other nodes and block signature
Expand Down
34 changes: 20 additions & 14 deletions crates/node/src/service/rpc/middleware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,6 @@ enum VersionMiddlewareError {
BodyReadError(#[from] hyper::Error),
#[error("Failed to parse JSON: {0}")]
JsonParseError(#[from] serde_json::Error),
#[error("Invalid request format")]
InvalidRequestFormat,
#[error("Invalid URL format")]
InvalidUrlFormat,
#[error("Invalid version specified")]
Expand Down Expand Up @@ -236,9 +234,6 @@ where
VersionMiddlewareError::InvalidVersion => {
ErrorObject::owned(-32600, "Invalid RPC version specified", None::<()>)
}
VersionMiddlewareError::InvalidRequestFormat => {
ErrorObject::owned(-32600, "Invalid JSON-RPC request format", None::<()>)
}
VersionMiddlewareError::UnsupportedVersion => {
ErrorObject::owned(-32601, "Unsupported RPC version specified", None::<()>)
}
Expand All @@ -248,7 +243,7 @@ where
let body = json!({
"jsonrpc": "2.0",
"error": error,
"id": 0
"id": null
})
.to_string();

Expand All @@ -267,18 +262,29 @@ async fn add_rpc_version_to_method(req: &mut hyper::Request<Body>) -> Result<(),
let version = RpcVersion::from_request_path(&path)?;

let whole_body = hyper::body::to_bytes(req.body_mut()).await?;
let mut json: Value = serde_json::from_slice(&whole_body)?;

if let Some(method) = json.get_mut("method").as_deref().and_then(Value::as_str) {
let new_method = format!("starknet_{}_{}", version.name(), method.strip_prefix("starknet_").unwrap_or(method));
let json: Value = serde_json::from_slice(&whole_body)?;

json["method"] = Value::String(new_method);
// in case of batched requests, the request is an array of JSON-RPC requests
let mut batched_request = false;
let mut items = if let Value::Array(items) = json {
batched_request = true;
items
} else {
return Err(VersionMiddlewareError::InvalidRequestFormat);
vec![json]
};

for item in items.iter_mut() {
if let Some(method) = item.get_mut("method").as_deref().and_then(Value::as_str) {
let new_method =
format!("starknet_{}_{}", version.name(), method.strip_prefix("starknet_").unwrap_or(method));

item["method"] = Value::String(new_method);
}
// we don't need to throw an error here, the request will be rejected later if the method is not supported
}

let new_body = Body::from(serde_json::to_vec(&json)?);
*req.body_mut() = new_body;
let response = if batched_request { serde_json::to_vec(&items)? } else { serde_json::to_vec(&items[0])? };
*req.body_mut() = Body::from(response);

Ok(())
}
82 changes: 82 additions & 0 deletions crates/tests/src/rpc/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,88 @@ mod test_rpc_read_calls {
assert_eq!(result, 1);
}

/// Fetches the latest block hash and number.
///
/// Example curl command:
///
/// ```bash
/// curl --location 'https://free-rpc.nethermind.io/sepolia-juno/' \
/// --header 'Content-Type: application/json' \
/// --data '[
/// {
/// "jsonrpc": "2.0",
/// "method": "starknet_blockHashAndNumber",
/// "params": {},
/// "id": 0
/// },
/// {
/// "jsonrpc": "2.0",
/// "method": "starknet_getBlockTransactionCount",
/// "params": {
/// "block_id": {
/// "block_number": 2
/// }
/// },
/// "id": 1
/// }
/// ]'
/// ```
#[rstest]
#[tokio::test]
async fn test_batched_requests_work() {
let madara = get_shared_state().await;

// use reqwest to send a batch request to the madara rpc.
// TODO: use a jsonrpc client instead of reqwest when we move
// to starknet-providers 0.12.0
let client = reqwest::Client::new();
let res = client
.post(madara.rpc_url.clone())
.json(&[
serde_json::json!({
"jsonrpc": "2.0",
"method": "starknet_blockHashAndNumber",
"params": {},
"id": 0
}),
serde_json::json!({
"jsonrpc": "2.0",
"method": "starknet_getBlockTransactionCount",
"params": {
"block_id": {
"block_number": 2
}
},
"id": 1
}),
])
.send()
.await
.unwrap();

let result = res.json::<serde_json::Value>().await.unwrap();

assert_eq!(
result[0],
serde_json::json!({
"jsonrpc": "2.0",
"result": {
"block_hash": "0x4177d1ba942a4ab94f86a476c06f0f9e02363ad410cdf177c54064788c9bcb5",
"block_number": 19
},
"id": 0
})
);
assert_eq!(
result[1],
serde_json::json!({
"jsonrpc": "2.0",
"result": 1,
"id": 1
})
);
}

/// Fetches a block with its transactions and receipts.
///
/// Example curl command:
Expand Down

0 comments on commit b79390b

Please sign in to comment.